/*
 * Copyright (C) 2005-2011 MaNGOS <http://www.getmangos.com/>
 *
 * Copyright (C) 2008-2011 Trinity <http://www.trinitycore.org/>
 *
 * Copyright (C) 2010-2011 ArkCORE <http://www.arkania.net/>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#ifndef __UNIT_H
#define __UNIT_H

#include "Common.h"
#include "Object.h"
#include "Opcodes.h"
#include "SpellAuraDefines.h"
#include "UpdateFields.h"
#include "SharedDefines.h"
#include "ThreatManager.h"
#include "HostileRefManager.h"
#include "FollowerReference.h"
#include "FollowerRefManager.h"
#include "EventProcessor.h"
#include "MotionMaster.h"
#include "DBCStructure.h"
#include "Path.h"
#include "WorldPacket.h"
#include "Timer.h"
#include <list>

#define WORLD_TRIGGER   12999

enum SpellInterruptFlags {
	SPELL_INTERRUPT_FLAG_MOVEMENT = 0x01, // why need this for instant?
	SPELL_INTERRUPT_FLAG_PUSH_BACK = 0x02, // push back
	SPELL_INTERRUPT_FLAG_INTERRUPT = 0x04, // interrupt
	SPELL_INTERRUPT_FLAG_AUTOATTACK = 0x08, // no
	SPELL_INTERRUPT_FLAG_ABORT_ON_DMG = 0x10,
// _complete_ interrupt on direct damage
//SPELL_INTERRUPT_UNK             = 0x20                // unk, 564 of 727 spells having this spell start with "Glyph"
};

// See SpellAuraInterruptFlags for other values definitions
enum SpellChannelInterruptFlags {
	CHANNEL_FLAG_DELAY = 0x4000
};

enum SpellAuraInterruptFlags {
	AURA_INTERRUPT_FLAG_HITBYSPELL = 0x00000001, // 0    removed when getting hit by a negative spell?
	AURA_INTERRUPT_FLAG_TAKE_DAMAGE = 0x00000002, // 1    removed by any damage
	AURA_INTERRUPT_FLAG_CAST = 0x00000004, // 2    cast any spells
	AURA_INTERRUPT_FLAG_MOVE = 0x00000008, // 3    removed by any movement
	AURA_INTERRUPT_FLAG_TURNING = 0x00000010, // 4    removed by any turning
	AURA_INTERRUPT_FLAG_JUMP = 0x00000020, // 5    removed by entering combat
	AURA_INTERRUPT_FLAG_NOT_MOUNTED = 0x00000040, // 6    removed by unmounting
	AURA_INTERRUPT_FLAG_NOT_ABOVEWATER = 0x00000080, // 7    removed by entering water
	AURA_INTERRUPT_FLAG_NOT_UNDERWATER = 0x00000100, // 8    removed by leaving water
	AURA_INTERRUPT_FLAG_NOT_SHEATHED = 0x00000200, // 9    removed by unsheathing
	AURA_INTERRUPT_FLAG_TALK = 0x00000400, // 10   talk to npc / loot? action on creature
	AURA_INTERRUPT_FLAG_USE = 0x00000800, // 11   mine/use/open action on gameobject
	AURA_INTERRUPT_FLAG_MELEE_ATTACK = 0x00001000, // 12   removed by attacking
	AURA_INTERRUPT_FLAG_SPELL_ATTACK = 0x00002000, // 13   ???
	AURA_INTERRUPT_FLAG_UNK14 = 0x00004000, // 14
	AURA_INTERRUPT_FLAG_TRANSFORM = 0x00008000, // 15   removed by transform?
	AURA_INTERRUPT_FLAG_UNK16 = 0x00010000, // 16
	AURA_INTERRUPT_FLAG_MOUNT = 0x00020000, // 17   misdirect, aspect, swim speed
	AURA_INTERRUPT_FLAG_NOT_SEATED = 0x00040000, // 18   removed by standing up (used by food and drink mostly and sleep/Fake Death like)
	AURA_INTERRUPT_FLAG_CHANGE_MAP = 0x00080000, // 19   leaving map/getting teleported
	AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION = 0x00100000, // 20   removed by auras that make you invulnerable, or make other to loose selection on you
	AURA_INTERRUPT_FLAG_UNK21 = 0x00200000, // 21
	AURA_INTERRUPT_FLAG_TELEPORTED = 0x00400000, // 22
	AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT = 0x00800000, // 23   removed by entering pvp combat
	AURA_INTERRUPT_FLAG_DIRECT_DAMAGE = 0x01000000, // 24   removed by any direct damage
	AURA_INTERRUPT_FLAG_LANDING = 0x02000000, // 25   removed by hitting the ground

	AURA_INTERRUPT_FLAG_NOT_VICTIM = (AURA_INTERRUPT_FLAG_HITBYSPELL
			| AURA_INTERRUPT_FLAG_TAKE_DAMAGE
			| AURA_INTERRUPT_FLAG_DIRECT_DAMAGE),
};

enum SpellModOp {
	SPELLMOD_DAMAGE = 0,
	SPELLMOD_DURATION = 1,
	SPELLMOD_THREAT = 2,
	SPELLMOD_EFFECT1 = 3,
	SPELLMOD_CHARGES = 4,
	SPELLMOD_RANGE = 5,
	SPELLMOD_RADIUS = 6,
	SPELLMOD_CRITICAL_CHANCE = 7,
	SPELLMOD_ALL_EFFECTS = 8,
	SPELLMOD_NOT_LOSE_CASTING_TIME = 9,
	SPELLMOD_CASTING_TIME = 10,
	SPELLMOD_COOLDOWN = 11,
	SPELLMOD_EFFECT2 = 12,
	SPELLMOD_IGNORE_ARMOR = 13,
	SPELLMOD_COST = 14,
	SPELLMOD_CRIT_DAMAGE_BONUS = 15,
	SPELLMOD_RESIST_MISS_CHANCE = 16,
	SPELLMOD_JUMP_TARGETS = 17,
	SPELLMOD_CHANCE_OF_SUCCESS = 18,
	SPELLMOD_ACTIVATION_TIME = 19,
	SPELLMOD_DAMAGE_MULTIPLIER = 20,
	SPELLMOD_GLOBAL_COOLDOWN = 21,
	SPELLMOD_DOT = 22,
	SPELLMOD_EFFECT3 = 23,
	SPELLMOD_BONUS_MULTIPLIER = 24,
	// spellmod 25
	SPELLMOD_PROC_PER_MINUTE = 26,
	SPELLMOD_VALUE_MULTIPLIER = 27,
	SPELLMOD_RESIST_DISPEL_CHANCE = 28,
	SPELLMOD_CRIT_DAMAGE_BONUS_2 = 29, //one not used spell
	SPELLMOD_SPELL_COST_REFUND_ON_FAIL = 30
};

#define MAX_SPELLMOD 32

enum SpellValueMod {
	SPELLVALUE_BASE_POINT0,
	SPELLVALUE_BASE_POINT1,
	SPELLVALUE_BASE_POINT2,
	SPELLVALUE_RADIUS_MOD,
	SPELLVALUE_MAX_TARGETS,
    SPELLVALUE_AURA_STACK,
};

typedef std::pair<SpellValueMod, int32> CustomSpellValueMod;
class CustomSpellValues: public std::vector<CustomSpellValueMod> {
public:
	void AddSpellMod(SpellValueMod mod, int32 value) {
		push_back(std::make_pair(mod, value));
	}
};

enum SpellFacingFlags {
	SPELL_FACING_FLAG_INFRONT = 0x0001
};

#define BASE_MINDAMAGE 1.0f
#define BASE_MAXDAMAGE 2.0f
#define BASE_ATTACK_TIME 2000

// byte value (UNIT_FIELD_BYTES_1, 0)
enum UnitStandStateType {
	UNIT_STAND_STATE_STAND = 0,
	UNIT_STAND_STATE_SIT = 1,
	UNIT_STAND_STATE_SIT_CHAIR = 2,
	UNIT_STAND_STATE_SLEEP = 3,
	UNIT_STAND_STATE_SIT_LOW_CHAIR = 4,
	UNIT_STAND_STATE_SIT_MEDIUM_CHAIR = 5,
	UNIT_STAND_STATE_SIT_HIGH_CHAIR = 6,
	UNIT_STAND_STATE_DEAD = 7,
	UNIT_STAND_STATE_KNEEL = 8,
	UNIT_STAND_STATE_SUBMERGED = 9
};

// byte flag value (UNIT_FIELD_BYTES_1, 2)
enum UnitStandFlags {
	UNIT_STAND_FLAGS_UNK1 = 0x01,
	UNIT_STAND_FLAGS_CREEP = 0x02,
	UNIT_STAND_FLAGS_UNK3 = 0x04,
	UNIT_STAND_FLAGS_UNK4 = 0x08,
	UNIT_STAND_FLAGS_UNK5 = 0x10,
	UNIT_STAND_FLAGS_ALL = 0xFF
};

// byte flags value (UNIT_FIELD_BYTES_1, 3)
enum UnitBytes1_Flags {
	UNIT_BYTE1_FLAG_ALWAYS_STAND = 0x01,
	UNIT_BYTE1_FLAG_UNK_2 = 0x02,
	UNIT_BYTE1_FLAG_UNTRACKABLE = 0x04,
	UNIT_BYTE1_FLAG_ALL = 0xFF
};

// high byte (3 from 0..3) of UNIT_FIELD_BYTES_2
enum ShapeshiftForm {
	FORM_NONE = 0x00,
	FORM_CAT = 0x01,
	FORM_TREE = 0x02,
	FORM_TRAVEL = 0x03,
	FORM_AQUA = 0x04,
	FORM_BEAR = 0x05,
	FORM_AMBIENT = 0x06,
	FORM_GHOUL = 0x07,
	FORM_DIREBEAR = 0x08,
	FORM_STEVES_GHOUL = 0x09,
	FORM_THARONJA_SKELETON = 0x0A,
	FORM_TEST_OF_STRENGTH = 0x0B,
	FORM_BLB_PLAYER = 0x0C,
	FORM_SHADOW_DANCE = 0x0D,
	FORM_CREATUREBEAR = 0x0E,
	FORM_CREATURECAT = 0x0F,
	FORM_GHOSTWOLF = 0x10,
	FORM_BATTLESTANCE = 0x11,
	FORM_DEFENSIVESTANCE = 0x12,
	FORM_BERSERKERSTANCE = 0x13,
	FORM_TEST = 0x14,
	FORM_ZOMBIE = 0x15,
	FORM_METAMORPHOSIS = 0x16,
	FORM_UNDEAD = 0x19,
	FORM_MASTER_ANGLER = 0x1A,
	FORM_FLIGHT_EPIC = 0x1B,
	FORM_SHADOW = 0x1C,
	FORM_FLIGHT = 0x1D,
	FORM_STEALTH = 0x1E,
	FORM_MOONKIN = 0x1F,
	FORM_SPIRITOFREDEMPTION = 0x20
};

// low byte (0 from 0..3) of UNIT_FIELD_BYTES_2
enum SheathState {
	SHEATH_STATE_UNARMED = 0, // non prepared weapon
	SHEATH_STATE_MELEE = 1, // prepared melee weapon
	SHEATH_STATE_RANGED = 2
// prepared ranged weapon
};

#define MAX_SHEATH_STATE    3

// byte (1 from 0..3) of UNIT_FIELD_BYTES_2
enum UnitPVPStateFlags {
	UNIT_BYTE2_FLAG_PVP = 0x01,
	UNIT_BYTE2_FLAG_UNK1 = 0x02,
	UNIT_BYTE2_FLAG_FFA_PVP = 0x04,
	UNIT_BYTE2_FLAG_SANCTUARY = 0x08,
	UNIT_BYTE2_FLAG_UNK4 = 0x10,
	UNIT_BYTE2_FLAG_UNK5 = 0x20,
	UNIT_BYTE2_FLAG_UNK6 = 0x40,
	UNIT_BYTE2_FLAG_UNK7 = 0x80
};

// byte (2 from 0..3) of UNIT_FIELD_BYTES_2
enum UnitRename {
	UNIT_CAN_BE_RENAMED = 0x01, UNIT_CAN_BE_ABANDONED = 0x02,
};

#define CREATURE_MAX_SPELLS     8
#define MAX_SPELL_CHARM         4
#define MAX_SPELL_VEHICLE       6
#define MAX_SPELL_POSSESS       8
#define MAX_SPELL_CONTROL_BAR   10

enum Swing {
	NOSWING = 0, SINGLEHANDEDSWING = 1, TWOHANDEDSWING = 2
};

enum VictimState {
	VICTIMSTATE_INTACT = 0, // set when attacker misses
	VICTIMSTATE_HIT = 1, // victim got clear/blocked hit
	VICTIMSTATE_DODGE = 2,
	VICTIMSTATE_PARRY = 3,
	VICTIMSTATE_INTERRUPT = 4,
	VICTIMSTATE_BLOCKS = 5, // unused? not set when blocked, even on full block
	VICTIMSTATE_EVADES = 6,
	VICTIMSTATE_IS_IMMUNE = 7,
	VICTIMSTATE_DEFLECTS = 8
};

enum HitInfo {
	HITINFO_NORMALSWING = 0x00000000, HITINFO_UNK1 = 0x00000001, // req correct packet structure
	HITINFO_NORMALSWING2 = 0x00000002,
	HITINFO_LEFTSWING = 0x00000004,
	HITINFO_UNK2 = 0x00000008,
	HITINFO_MISS = 0x00000010,
	HITINFO_ABSORB = 0x00000020, // absorbed damage
	HITINFO_ABSORB2 = 0x00000040, // absorbed damage
	HITINFO_RESIST = 0x00000080, // resisted atleast some damage
	HITINFO_RESIST2 = 0x00000100, // resisted atleast some damage
	HITINFO_CRITICALHIT = 0x00000200, // critical hit
	// 0x00000400
	// 0x00000800
	// 0x00001000
	HITINFO_BLOCK = 0x00002000, // blocked damage
	// 0x00004000
	// 0x00008000
	HITINFO_GLANCING = 0x00010000,
	HITINFO_CRUSHING = 0x00020000,
	HITINFO_NOACTION = 0x00040000, // guessed
	// 0x00080000
	// 0x00100000
	HITINFO_SWINGNOHITSOUND = 0x00200000, // guessed
	// 0x00400000
	HITINFO_UNK3 = 0x00800000
};

//i would like to remove this: (it is defined in item.h
enum InventorySlot {
	NULL_BAG = 0, NULL_SLOT = 255
};

struct FactionTemplateEntry;
struct SpellEntry;
struct SpellValue;

class AuraApplication;
class Aura;
class UnitAura;
class AuraEffect;
class Creature;
class Spell;
class DynamicObject;
class GameObject;
class Item;
class Pet;
class PetAura;
class Minion;
class Guardian;
class UnitAI;
class Totem;
class Transport;
class Vehicle;

struct SpellImmune {
	uint32 type;
	uint32 spellId;
};

typedef std::list<SpellImmune> SpellImmuneList;

enum UnitModifierType {
	BASE_VALUE = 0,
	BASE_PCT = 1,
	TOTAL_VALUE = 2,
	TOTAL_PCT = 3,
	MODIFIER_TYPE_END = 4
};

enum WeaponDamageRange {
	MINDAMAGE, MAXDAMAGE
};

enum DamageTypeToSchool {
	RESISTANCE, DAMAGE_DEALT, DAMAGE_TAKEN
};

enum AuraRemoveMode {
	AURA_REMOVE_NONE = 0, AURA_REMOVE_BY_DEFAULT = 1, // scripted remove, remove by stack with aura with different ids and sc aura remove
	AURA_REMOVE_BY_STACK, // replace by aura with same id
	AURA_REMOVE_BY_CANCEL,
	AURA_REMOVE_BY_ENEMY_SPELL, // dispel and absorb aura destroy
	AURA_REMOVE_BY_EXPIRE, // aura duration has ended
	AURA_REMOVE_BY_DEATH
};

enum TriggerCastFlags
{
    TRIGGERED_NONE                                  = 0x00000000,   //! Not triggered
    TRIGGERED_IGNORE_GCD                            = 0x00000001,   //! Will ignore GCD
    TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD          = 0x00000002,   //! Will ignore Spell and Category cooldowns
    TRIGGERED_IGNORE_POWER_AND_REAGENT_COST         = 0x00000004,   //! Will ignore power and reagent cost
    TRIGGERED_IGNORE_CAST_ITEM                      = 0x00000008,   //! Will not take away cast item or update related achievement criteria
    TRIGGERED_IGNORE_AURA_SCALING                   = 0x00000010,   //! Will ignore aura scaling
    TRIGGERED_IGNORE_CAST_IN_PROGRESS               = 0x00000020,   //! Will not check if a current cast is in progress
    TRIGGERED_IGNORE_COMBO_POINTS                   = 0x00000040,   //! Will ignore combo point requirement
    TRIGGERED_CAST_DIRECTLY                         = 0x00000080,   //! In Spell::prepare, will be cast directly without setting containers for executed spell
    TRIGGERED_IGNORE_AURA_INTERRUPT_FLAGS           = 0x00000100,   //! Will ignore interruptible aura's at cast
    TRIGGERED_IGNORE_SET_FACING                     = 0x00000200,   //! Will not adjust facing to target (if any)
    TRIGGERED_IGNORE_SHAPESHIFT                     = 0x00000400,   //! Will ignore shapeshift checks
    TRIGGERED_IGNORE_CASTER_AURASTATE               = 0x00000800,   //! Will ignore caster aura states including combat requirements and death state
    TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE   = 0x00002000,   //! Will ignore mounted/on vehicle restrictions
    TRIGGERED_IGNORE_CASTER_AURAS                   = 0x00010000,   //! Will ignore caster aura restrictions or requirements
    TRIGGERED_DISALLOW_PROC_EVENTS                  = 0x00020000,   //! Disallows proc events from triggered spell (default)
    TRIGGERED_DONT_REPORT_CAST_ERROR                = 0x00040000,   //! Will return SPELL_FAILED_DONT_REPORT in CheckCast functions
    TRIGGERED_FULL_MASK                             = 0xFFFFFFFF,
};

enum UnitMods {
	UNIT_MOD_STAT_STRENGTH, // UNIT_MOD_STAT_STRENGTH..UNIT_MOD_STAT_SPIRIT must be in existed order, it's accessed by index values of Stats enum.
	UNIT_MOD_STAT_AGILITY,
	UNIT_MOD_STAT_STAMINA,
	UNIT_MOD_STAT_INTELLECT,
	UNIT_MOD_STAT_SPIRIT,
	UNIT_MOD_HEALTH,
	UNIT_MOD_MANA, // UNIT_MOD_MANA..UNIT_MOD_RUNIC_POWER must be in existed order, it's accessed by index values of Powers enum.
	UNIT_MOD_RAGE,
	UNIT_MOD_FOCUS,
	UNIT_MOD_ENERGY,
	UNIT_MOD_HAPPINESS,
	UNIT_MOD_RUNE,
	UNIT_MOD_RUNIC_POWER,
	UNIT_MOD_ARMOR, // UNIT_MOD_ARMOR..UNIT_MOD_RESISTANCE_ARCANE must be in existed order, it's accessed by index values of SpellSchools enum.
	UNIT_MOD_RESISTANCE_HOLY,
	UNIT_MOD_RESISTANCE_FIRE,
	UNIT_MOD_RESISTANCE_NATURE,
	UNIT_MOD_RESISTANCE_FROST,
	UNIT_MOD_RESISTANCE_SHADOW,
	UNIT_MOD_RESISTANCE_ARCANE,
	UNIT_MOD_ATTACK_POWER_POS,
	UNIT_MOD_ATTACK_POWER_NEG,
	UNIT_MOD_ATTACK_POWER_RANGED_POS,
	UNIT_MOD_ATTACK_POWER_RANGED_NEG,
	UNIT_MOD_DAMAGE_MAINHAND,
	UNIT_MOD_DAMAGE_OFFHAND,
	UNIT_MOD_DAMAGE_RANGED,
	UNIT_MOD_END,
	// synonyms
	UNIT_MOD_STAT_START = UNIT_MOD_STAT_STRENGTH,
	UNIT_MOD_STAT_END = UNIT_MOD_STAT_SPIRIT + 1,
	UNIT_MOD_RESISTANCE_START = UNIT_MOD_ARMOR,
	UNIT_MOD_RESISTANCE_END = UNIT_MOD_RESISTANCE_ARCANE + 1,
	UNIT_MOD_POWER_START = UNIT_MOD_MANA,
	UNIT_MOD_POWER_END = UNIT_MOD_RUNIC_POWER + 1
};

enum BaseModGroup {
	CRIT_PERCENTAGE,
	RANGED_CRIT_PERCENTAGE,
	OFFHAND_CRIT_PERCENTAGE,
	SHIELD_BLOCK_VALUE,
	BASEMOD_END
};

enum BaseModType {
	FLAT_MOD, PCT_MOD
};

#define MOD_END (PCT_MOD+1)

enum DeathState {
	ALIVE = 0,
	JUST_DIED = 1,
	CORPSE = 2,
	DEAD = 3,
	JUST_ALIVED = 4,
	DEAD_FALLING = 5
};

enum UnitState {
	UNIT_STAT_DIED = 0x00000001, UNIT_STAT_MELEE_ATTACKING = 0x00000002, // player is melee attacking someone
	//UNIT_STAT_MELEE_ATTACK_BY = 0x00000004,                     // player is melee attack by someone
	UNIT_STAT_STUNNED = 0x00000008,
	UNIT_STAT_ROAMING = 0x00000010,
	UNIT_STAT_CHASE = 0x00000020,
	//UNIT_STAT_SEARCHING       = 0x00000040,
	UNIT_STAT_FLEEING = 0x00000080,
	UNIT_STAT_IN_FLIGHT = 0x00000100, // player is in flight mode
	UNIT_STAT_FOLLOW = 0x00000200,
	UNIT_STAT_ROOT = 0x00000400,
	UNIT_STAT_CONFUSED = 0x00000800,
	UNIT_STAT_DISTRACTED = 0x00001000,
	UNIT_STAT_ISOLATED = 0x00002000, // area auras do not affect other players
	UNIT_STAT_ATTACK_PLAYER = 0x00004000,
	UNIT_STAT_CASTING = 0x00008000,
	UNIT_STAT_POSSESSED = 0x00010000,
	UNIT_STAT_CHARGING = 0x00020000,
	UNIT_STAT_JUMPING = 0x00040000,
	UNIT_STAT_ONVEHICLE = 0x00080000,
	UNIT_STAT_MOVE = 0x00100000,
	UNIT_STAT_ROTATING = 0x00200000,
	UNIT_STAT_EVADE = 0x00400000,
	UNIT_STAT_UNATTACKABLE = (UNIT_STAT_IN_FLIGHT | UNIT_STAT_ONVEHICLE),
	UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE),
	UNIT_STAT_CONTROLLED = (UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED
			| UNIT_STAT_FLEEING),
	UNIT_STAT_LOST_CONTROL = (UNIT_STAT_CONTROLLED | UNIT_STAT_JUMPING
			| UNIT_STAT_CHARGING),
	UNIT_STAT_SIGHTLESS = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_EVADE),
	UNIT_STAT_CANNOT_AUTOATTACK = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_CASTING),
	UNIT_STAT_CANNOT_TURN = (UNIT_STAT_LOST_CONTROL | UNIT_STAT_ROTATING),
	UNIT_STAT_ALL_STATE = 0xffffffff
//(UNIT_STAT_STOPPED | UNIT_STAT_MOVING | UNIT_STAT_IN_COMBAT | UNIT_STAT_IN_FLIGHT)
};

enum UnitMoveType {
	MOVE_WALK = 0,
	MOVE_RUN = 1,
	MOVE_RUN_BACK = 2,
	MOVE_SWIM = 3,
	MOVE_SWIM_BACK = 4,
	MOVE_TURN_RATE = 5,
	MOVE_FLIGHT = 6,
	MOVE_FLIGHT_BACK = 7,
	MOVE_PITCH_RATE = 8
};

#define MAX_MOVE_TYPE     9

extern float baseMoveSpeed[MAX_MOVE_TYPE];
extern float playerBaseMoveSpeed[MAX_MOVE_TYPE];

enum WeaponAttackType {
	BASE_ATTACK = 0, OFF_ATTACK = 1, RANGED_ATTACK = 2, MAX_ATTACK
};

enum CombatRating {
	CR_WEAPON_SKILL = 0,
	CR_DEFENSE_SKILL = 1,
	CR_DODGE = 2,
	CR_PARRY = 3,
	CR_BLOCK = 4,
	CR_HIT_MELEE = 5,
	CR_HIT_RANGED = 6,
	CR_HIT_SPELL = 7,
	CR_CRIT_MELEE = 8,
	CR_CRIT_RANGED = 9,
	CR_CRIT_SPELL = 10,
	CR_HIT_TAKEN_MELEE = 11,
	CR_HIT_TAKEN_RANGED = 12,
	CR_HIT_TAKEN_SPELL = 13,
	CR_RESILIENCE_CRIT_TAKEN = 14,
	CR_RESILIENCE_PLAYER_DAMAGE_TAKEN = 15,
	CR_CRIT_TAKEN_SPELL = 16,
	CR_HASTE_MELEE = 17,
	CR_HASTE_RANGED = 18,
	CR_HASTE_SPELL = 19,
	CR_WEAPON_SKILL_MAINHAND = 20,
	CR_WEAPON_SKILL_OFFHAND = 21,
	CR_WEAPON_SKILL_RANGED = 22,
	CR_EXPERTISE = 23,
	CR_ARMOR_PENETRATION = 24,
	CR_MASTERY = 25
};

#define MAX_COMBAT_RATING         26

enum DamageEffectType {
	DIRECT_DAMAGE = 0, // used for normal weapon damage (not for class abilities or spells)
	SPELL_DIRECT_DAMAGE = 1, // spell/class abilities damage
	DOT = 2,
	HEAL = 3,
	NODAMAGE = 4, // used also in case when damage applied to health but not applied to spell channelInterruptFlags/etc
	SELF_DAMAGE = 5
};

// Value masks for UNIT_FIELD_FLAGS
enum UnitFlags {
	UNIT_FLAG_UNK_0 = 0x00000001, UNIT_FLAG_NON_ATTACKABLE = 0x00000002, // not attackable
	UNIT_FLAG_DISABLE_MOVE = 0x00000004,
	UNIT_FLAG_PVP_ATTACKABLE = 0x00000008, // allow apply pvp rules to attackable state in addition to faction dependent state
	UNIT_FLAG_RENAME = 0x00000010,
	UNIT_FLAG_PREPARATION = 0x00000020, // don't take reagents for spells with SPELL_ATTR5_NO_REAGENT_WHILE_PREP
	UNIT_FLAG_UNK_6 = 0x00000040,
	UNIT_FLAG_NOT_ATTACKABLE_1 = 0x00000080, // ?? (UNIT_FLAG_PVP_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE
	UNIT_FLAG_OOC_NOT_ATTACKABLE = 0x00000100, // 2.0.8 - (OOC Out Of Combat) Can not be attacked when not in combat. Removed if unit for some reason enter combat.
	UNIT_FLAG_PASSIVE = 0x00000200, // makes you unable to attack everything. Almost identical to our "civilian"-term. Will ignore it's surroundings and not engage in combat unless "called upon" or engaged by another unit.
	UNIT_FLAG_LOOTING = 0x00000400, // loot animation
	UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8
	UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3
	UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1
	UNIT_FLAG_UNK_14 = 0x00004000, // 2.0.8
	UNIT_FLAG_UNK_15 = 0x00008000,
	UNIT_FLAG_UNK_16 = 0x00010000,
	UNIT_FLAG_PACIFIED = 0x00020000, // 3.0.3 ok
	UNIT_FLAG_STUNNED = 0x00040000, // 3.0.3 ok
	UNIT_FLAG_IN_COMBAT = 0x00080000,
	UNIT_FLAG_TAXI_FLIGHT = 0x00100000, // disable casting at client side spell not allowed by taxi flight (mounted?), probably used with 0x4 flag
	UNIT_FLAG_DISARMED = 0x00200000, // 3.0.3, disable melee spells casting..., "Required melee weapon" added to melee spells tooltip.
	UNIT_FLAG_CONFUSED = 0x00400000,
	UNIT_FLAG_FLEEING = 0x00800000,
	UNIT_FLAG_PLAYER_CONTROLLED = 0x01000000, // used in spell Eyes of the Beast for pet... let attack by controlled creature
	UNIT_FLAG_NOT_SELECTABLE = 0x02000000,
	UNIT_FLAG_SKINNABLE = 0x04000000,
	UNIT_FLAG_MOUNT = 0x08000000,
	UNIT_FLAG_UNK_28 = 0x10000000,
	UNIT_FLAG_UNK_29 = 0x20000000, // used in Feing Death spell
	UNIT_FLAG_SHEATHE = 0x40000000,
	UNIT_FLAG_UNK_31 = 0x80000000
};

// Value masks for UNIT_FIELD_FLAGS_2
enum UnitFlags2 {
	UNIT_FLAG2_FEIGN_DEATH 				= 0x00000001, 
	UNIT_FLAG2_UNK1 					= 0x00000002, // Hide unit model (show only player equip)
	UNIT_FLAG2_IGNORE_REPUTATION    	= 0x00000004,
	UNIT_FLAG2_COMPREHEND_LANG 			= 0x00000008,
	UNIT_FLAG2_MIRROR_IMAGE 			= 0x00000010,
	UNIT_FLAG2_FORCE_MOVE 				= 0x00000040,
	UNIT_FLAG2_DISARM_OFFHAND 			= 0x00000080,
	UNIT_FLAG2_DISARM_RANGED 			= 0x00000400, //this does not disable ranged weapon display (maybe additional flag needed?)
	UNIT_FLAG2_REGENERATE_POWER 		= 0x00000800,
	UNIT_FLAG2_ALLOW_ENEMY_INTERACT 	= 0x00004000,
	UNIT_FLAG2_ALLOW_CHEAT_SPELLS   	= 0x00040000, // allows casting spells with AttributesEx7 & SPELL_ATTR7_IS_CHEAT_SPELL	
	UNIT_FLAG2_WORGEN_TRANSFORM 		= 0x00080000, // transform to worgen
	UNIT_FLAG2_WORGEN_TRANSFORM2 		= 0x00100000, // transform to worgen, less animation
	UNIT_FLAG2_WORGEN_TRANSFORM3 		= 0x00200000
// transform to worgen, less animation(why twice?)
};

#define IN_WORGEN_FORM (UNIT_FLAG2_WORGEN_TRANSFORM|UNIT_FLAG2_WORGEN_TRANSFORM2|UNIT_FLAG2_WORGEN_TRANSFORM3)

/// Non Player Character flags
enum NPCFlags {
	UNIT_NPC_FLAG_NONE = 0x00000000, UNIT_NPC_FLAG_GOSSIP = 0x00000001, // 100%
	UNIT_NPC_FLAG_QUESTGIVER = 0x00000002, // guessed, probably ok
	UNIT_NPC_FLAG_UNK1 = 0x00000004,
	UNIT_NPC_FLAG_UNK2 = 0x00000008,
	UNIT_NPC_FLAG_TRAINER = 0x00000010, // 100%
	UNIT_NPC_FLAG_TRAINER_CLASS = 0x00000020, // 100%
	UNIT_NPC_FLAG_TRAINER_PROFESSION = 0x00000040, // 100%
	UNIT_NPC_FLAG_VENDOR = 0x00000080, // 100%
	UNIT_NPC_FLAG_VENDOR_AMMO = 0x00000100, // 100%, general goods vendor
	UNIT_NPC_FLAG_VENDOR_FOOD = 0x00000200, // 100%
	UNIT_NPC_FLAG_VENDOR_POISON = 0x00000400, // guessed
	UNIT_NPC_FLAG_VENDOR_REAGENT = 0x00000800, // 100%
	UNIT_NPC_FLAG_REPAIR = 0x00001000, // 100%
	UNIT_NPC_FLAG_FLIGHTMASTER = 0x00002000, // 100%
	UNIT_NPC_FLAG_SPIRITHEALER = 0x00004000, // guessed
	UNIT_NPC_FLAG_SPIRITGUIDE = 0x00008000, // guessed
	UNIT_NPC_FLAG_INNKEEPER = 0x00010000, // 100%
	UNIT_NPC_FLAG_BANKER = 0x00020000, // 100%
	UNIT_NPC_FLAG_PETITIONER = 0x00040000, // 100% 0xC0000 = guild petitions, 0x40000 = arena team petitions
	UNIT_NPC_FLAG_TABARDDESIGNER = 0x00080000, // 100%
	UNIT_NPC_FLAG_BATTLEMASTER = 0x00100000, // 100%
	UNIT_NPC_FLAG_AUCTIONEER = 0x00200000, // 100%
	UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // 100%
	UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode
	UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click), dynamic, set at loading and don't must be set in DB
	UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x02000000, // players with mounts that have vehicle data should have it set
	UNIT_NPC_FLAG_REFORGER = 0x08000000,
// can reforge
};

enum MovementFlags {
	MOVEMENTFLAG_NONE = 0x00000000,
	MOVEMENTFLAG_FORWARD = 0x00000001,
	MOVEMENTFLAG_BACKWARD = 0x00000002,
	MOVEMENTFLAG_STRAFE_LEFT = 0x00000004,
	MOVEMENTFLAG_STRAFE_RIGHT = 0x00000008,
	MOVEMENTFLAG_LEFT = 0x00000010,
	MOVEMENTFLAG_RIGHT = 0x00000020,
	MOVEMENTFLAG_PITCH_UP = 0x00000040,
	MOVEMENTFLAG_PITCH_DOWN = 0x00000080,
	MOVEMENTFLAG_WALKING = 0x00000100, // Walking
	MOVEMENTFLAG_ONTRANSPORT = 0x00000200, // Used for flying on some creatures
	MOVEMENTFLAG_LEVITATING = 0x00000400,
	MOVEMENTFLAG_ROOT = 0x00000800,
	MOVEMENTFLAG_JUMPING = 0x00001000,
	MOVEMENTFLAG_FALLING = 0x00002000, // damage dealt on that type of falling
	MOVEMENTFLAG_PENDING_STOP = 0x00004000,
	MOVEMENTFLAG_PENDING_STRAFE_STOP = 0x00008000,
	MOVEMENTFLAG_PENDING_FORWARD = 0x00010000,
	MOVEMENTFLAG_PENDING_BACKWARD = 0x00020000,
	MOVEMENTFLAG_PENDING_STRAFE_LEFT = 0x00040000,
	MOVEMENTFLAG_PENDING_STRAFE_RIGHT = 0x00080000,
	MOVEMENTFLAG_PENDING_ROOT = 0x00100000,
	MOVEMENTFLAG_SWIMMING = 0x00200000, // appears with fly flag also
	MOVEMENTFLAG_ASCENDING = 0x00400000, // press "space" when flying
	MOVEMENTFLAG_DESCENDING = 0x00800000,
	MOVEMENTFLAG_CAN_FLY = 0x01000000, // can fly
	MOVEMENTFLAG_FLYING = 0x02000000, // hover
	MOVEMENTFLAG_SPLINE_ELEVATION = 0x04000000, // used for flight paths
	MOVEMENTFLAG_SPLINE_ENABLED = 0x08000000, // used for flight paths
	MOVEMENTFLAG_WATERWALKING = 0x10000000, // prevent unit from falling through water
	MOVEMENTFLAG_FALLING_SLOW = 0x20000000, // active rogue safe fall spell (passive)
	MOVEMENTFLAG_HOVER = 0x40000000, // hover, cannot jump

	MOVEMENTFLAG_MOVING = MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD
			| MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT
			| MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN
			| MOVEMENTFLAG_JUMPING | MOVEMENTFLAG_FALLING
			| MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_SPLINE_ELEVATION,
	MOVEMENTFLAG_TURNING = MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT,
};
enum MovementFlags2 {
	MOVEMENTFLAG2_NONE = 0x00000000,
	MOVEMENTFLAG2_NO_STRAFE = 0x00000001,
	MOVEMENTFLAG2_NO_JUMPING = 0x00000002,
	MOVEMENTFLAG2_UNK3 = 0x00000004, // Overrides various clientside checks
	MOVEMENTFLAG2_FULL_SPEED_TURNING = 0x00000008,
	MOVEMENTFLAG2_FULL_SPEED_PITCHING = 0x00000010,
	MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING = 0x00000020,
	MOVEMENTFLAG2_UNK7 = 0x00000040,
	MOVEMENTFLAG2_UNK8 = 0x00000080,
	MOVEMENTFLAG2_UNK9 = 0x00000100,
	MOVEMENTFLAG2_UNK10 = 0x00000200,
	MOVEMENTFLAG2_INTERPOLATED_MOVEMENT = 0x00000400,
	MOVEMENTFLAG2_INTERPOLATED_TURNING = 0x00000800,
	MOVEMENTFLAG2_INTERPOLATED_PITCHING = 0x00001000,
	MOVEMENTFLAG2_UNK14 = 0x00002000,
	MOVEMENTFLAG2_UNK15 = 0x00004000,
	MOVEMENTFLAG2_UNK16 = 0x00008000,

	// player only?
	MOVEMENTFLAG2_INTERPOLATED = MOVEMENTFLAG2_INTERPOLATED_MOVEMENT
			| MOVEMENTFLAG2_INTERPOLATED_TURNING
			| MOVEMENTFLAG2_INTERPOLATED_PITCHING
};
enum SplineFlags {
	SPLINEFLAG_NONE 			 = 0x00000000,
	SPLINEFLAG_FORWARD 			 = 0x00000001,
	SPLINEFLAG_BACKWARD			 = 0x00000002,
	SPLINEFLAG_STRAFE_LEFT 		 = 0x00000004,
	SPLINEFLAG_STRAFE_RIGHT 	 = 0x00000008,
	SPLINEFLAG_LEFT 			 = 0x00000010,
	SPLINEFLAG_RIGHT 			 = 0x00000020,
	SPLINEFLAG_PITCH_UP 		 = 0x00000040,
	SPLINEFLAG_PITCH_DOWN 		 = 0x00000080,
	SPLINEFLAG_DONE				 = 0x00000100,
	SPLINEFLAG_FALLING 			 = 0x00000200,
	SPLINEFLAG_NO_SPLINE 		 = 0x00000400,
	SPLINEFLAG_TRAJECTORY 	     = 0x00000800,
	SPLINEFLAG_WALKING 			 = 0x00001000,
	SPLINEFLAG_FLYING 			 = 0x00002000,
	SPLINEFLAG_KNOCKBACK 		 = 0x00004000,
	SPLINEFLAG_FINAL_POINT 	 	 = 0x00008000,
	SPLINEFLAG_FINAL_TARGET 	 = 0x00010000,
	SPLINEFLAG_FINAL_FACING 	 = 0x00020000,
	SPLINEFLAG_CATMULL_ROM 		 = 0x00040000,
	SPLINEFLAG_UNKNOWN20 		 = 0x00080000,
	SPLINEFLAG_UNKNOWN21 		 = 0x00100000,
	SPLINEFLAG_ANIMATIONTIER	 = 0x00200000,
	SPLINEFLAG_UNKNOWN23		 = 0x00400000,
	SPLINEFLAG_TRANSPORT		 = 0x00800000,
	SPLINEFLAG_UNKNOWN25		 = 0x01000000,
	SPLINEFLAG_UNKNOWN26		 = 0x02000000,
	SPLINEFLAG_UNKNOWN27		 = 0x04000000,
	SPLINEFLAG_UNKNOWN28		 = 0x08000000,
	SPLINEFLAG_UNKNOWN29 		 = 0x10000000,
	SPLINEFLAG_ANIMATION 		 = 0x20000000,
	SPLINEFLAG_UNKNOWN31 		 = 0x40000000,
	SPLINEFLAG_UNKNOWN32 		 = 0x80000000,

	SPLINEFLAG_GLIDE = SPLINEFLAG_WALKING | SPLINEFLAG_FLYING,
};

enum SplineMode {
	SPLINEMODE_LINEAR = 0, SPLINEMODE_CATMULL_ROM = 1, SPLINEMODE_BEZIER3 = 2
};

enum SplineType {
	SPLINETYPE_NORMAL = 0,
	SPLINETYPE_STOP = 1,
	SPLINETYPE_FACING_SPOT = 2,
	SPLINETYPE_FACING_TARGET = 3,
	SPLINETYPE_FACING_ANGLE = 4
};

enum UnitTypeMask {
	UNIT_MASK_NONE = 0x00000000,
	UNIT_MASK_SUMMON = 0x00000001,
	UNIT_MASK_MINION = 0x00000002,
	UNIT_MASK_GUARDIAN = 0x00000004,
	UNIT_MASK_TOTEM = 0x00000008,
	UNIT_MASK_PET = 0x00000010,
	UNIT_MASK_VEHICLE = 0x00000020,
	UNIT_MASK_PUPPET = 0x00000040,
	UNIT_MASK_HUNTER_PET = 0x00000080,
	UNIT_MASK_CONTROLABLE_GUARDIAN = 0x00000100,
	UNIT_MASK_ACCESSORY = 0x00000200,
};

enum DiminishingLevels {
	DIMINISHING_LEVEL_1 = 0,
	DIMINISHING_LEVEL_2 = 1,
	DIMINISHING_LEVEL_3 = 2,
	DIMINISHING_LEVEL_IMMUNE = 3,
	DIMINISHING_LEVEL_4 = 3,
	DIMINISHING_LEVEL_TAUNT_IMMUNE = 4,
};

struct DiminishingReturn {
	DiminishingReturn(DiminishingGroup group, uint32 t, uint32 count) :
			DRGroup(group), stack(0), hitTime(t), hitCount(count) {
	}

	DiminishingGroup DRGroup :16;
	uint16 stack :16;
	uint32 hitTime;
	uint32 hitCount;
};

enum MeleeHitOutcome {
	MELEE_HIT_EVADE,
	MELEE_HIT_MISS,
	MELEE_HIT_DODGE,
	MELEE_HIT_BLOCK,
	MELEE_HIT_PARRY,
	MELEE_HIT_GLANCING,
	MELEE_HIT_CRIT,
	MELEE_HIT_CRUSHING,
	MELEE_HIT_NORMAL
};

struct CleanDamage {
	CleanDamage(uint32 mitigated, uint32 absorbed, WeaponAttackType _attackType,
			MeleeHitOutcome _hitOutCome) :
			absorbed_damage(absorbed), mitigated_damage(mitigated), attackType(
					_attackType), hitOutCome(_hitOutCome) {
	}

	uint32 absorbed_damage;
	uint32 mitigated_damage;

	WeaponAttackType attackType;
	MeleeHitOutcome hitOutCome;
};

class DamageInfo {
private:
	Unit * const m_attacker;
	Unit * const m_victim;
	DamageEffectType const m_damageType;
	SpellEntry const * const m_spellInfo;
	SpellSchoolMask const m_schoolMask;
	uint32 m_damage;
	uint32 m_absorb;
	uint32 m_resist;
	uint32 m_block;
public:
	explicit DamageInfo(Unit * _attacker, Unit * _victim, uint32 _damage,
			SpellEntry const * _spellInfo, SpellSchoolMask _schoolMask,
			DamageEffectType _damageType) :
			m_attacker(_attacker), m_victim(_victim), m_damageType(_damageType), m_spellInfo(
					_spellInfo), m_schoolMask(_schoolMask), m_damage(_damage) {
		m_absorb = 0;
		m_resist = 0;
		m_block = 0;
	}
	void ModifyDamage(int32 amount) {
		amount = std::min(amount, int32(GetDamage()));
		m_damage += amount;
	}
	void AbsorbDamage(uint32 amount) {
		amount = std::min(amount, GetDamage());
		m_absorb += amount;
		m_damage -= amount;
	}
	void ResistDamage(uint32 amount) {
		amount = std::min(amount, GetDamage());
		m_resist += amount;
		m_damage -= amount;
	}
	void BlockDamage(uint32 amount) {
		amount = std::min(amount, GetDamage());
		m_block += amount;
		m_damage -= amount;
	}
	Unit * GetAttacker() const {
		return m_attacker;
	}
	;
	Unit * GetVictim() const {
		return m_victim;
	}
	;
	DamageEffectType const GetDamageType() const {
		return m_damageType;
	}
	;
	SpellEntry const * GetSpellInfo() const {
		return m_spellInfo;
	}
	;
	SpellSchoolMask const GetSchoolMask() const {
		return m_schoolMask;
	}
	;
	uint32 GetDamage() const {
		return m_damage;
	}
	;
	uint32 GetAbsorb() const {
		return m_absorb;
	}
	;
	uint32 GetResist() const {
		return m_resist;
	}
	;
	uint32 GetBlock() const {
		return m_block;
	}
	;
};

// Struct for use in Unit::CalculateMeleeDamage
// Need create structure like in SMSG_ATTACKERSTATEUPDATE opcode
struct CalcDamageInfo {
	Unit *attacker; // Attacker
	Unit *target; // Target for damage
	uint32 damageSchoolMask;
	uint32 damage;
	uint32 absorb;
	uint32 resist;
	uint32 blocked_amount;
	uint32 HitInfo;
	uint32 TargetState;
// Helper
	WeaponAttackType attackType; //
	uint32 procAttacker;
	uint32 procVictim;
	uint32 procEx;
	uint32 cleanDamage; // Used only for rage calculation
	MeleeHitOutcome hitOutCome; // TODO: remove this field (need use TargetState)
};

// Spell damage info structure based on structure sending in SMSG_SPELLNONMELEEDAMAGELOG opcode
struct SpellNonMeleeDamage {
	SpellNonMeleeDamage(Unit *_attacker, Unit *_target, uint32 _SpellID,
			uint32 _schoolMask) :
			target(_target), attacker(_attacker), SpellID(_SpellID), damage(0), overkill(
					0), schoolMask(_schoolMask), absorb(0), resist(0), physicalLog(
					false), unused(false), blocked(0), HitInfo(0), cleanDamage(
					0) {
	}

	Unit *target;
	Unit *attacker;
	uint32 SpellID;
	uint32 damage;
	uint32 overkill;
	uint32 schoolMask;
	uint32 absorb;
	uint32 resist;
	bool physicalLog;
	bool unused;
	uint32 blocked;
	uint32 HitInfo;
	// Used for help
	uint32 cleanDamage;
};

struct SpellPeriodicAuraLogInfo {
	SpellPeriodicAuraLogInfo(AuraEffect const *_auraEff, uint32 _damage,
			uint32 _overDamage, uint32 _absorb, uint32 _resist,
			float _multiplier, bool _critical) :
			auraEff(_auraEff), damage(_damage), overDamage(_overDamage), absorb(
					_absorb), resist(_resist), multiplier(_multiplier), critical(
					_critical) {
	}

	AuraEffect const * auraEff;
	uint32 damage;
	uint32 overDamage; // overkill/overheal
	uint32 absorb;
	uint32 resist;
	float multiplier;
	bool critical;
};

uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo,
		SpellMissInfo missCondition);

enum UnitAnimationState
{
    ANIMATION_ON_GROUND = 0,
    ANIMATION_SWIMMING  = 1,
    ANIMATION_HOVER     = 2,
    ANIMATION_FLYING    = 3,
};
		
struct MonsterMoveData
{
    MonsterMoveData() : SplineFlag(0), AnimationState(ANIMATION_ON_GROUND), Time(0), SpeedZ(0.0f) {}
    Position DestLocation;
    uint32 SplineFlag;
    UnitAnimationState AnimationState;  // Only used with SPLINEFLAG_ANIMATIONTIER
    uint32 Time;
    float SpeedZ;                       // Only used with SPLINEFLAG_TRAJECTORY
};
		
#define MAX_DECLINED_NAME_CASES 5

struct DeclinedName {
	std::string name[MAX_DECLINED_NAME_CASES];
};

enum CurrentSpellTypes {
	CURRENT_MELEE_SPELL = 0,
	CURRENT_GENERIC_SPELL = 1,
	CURRENT_AUTOREPEAT_SPELL = 2,
	CURRENT_CHANNELED_SPELL = 3
};

#define CURRENT_FIRST_NON_MELEE_SPELL 1
#define CURRENT_MAX_SPELL             4

enum ActiveStates {
	ACT_PASSIVE = 0x01, // 0x01 - passive
	ACT_DISABLED = 0x81, // 0x80 - castable
	ACT_ENABLED = 0xC1, // 0x40 | 0x80 - auto cast + castable
	ACT_COMMAND = 0x07, // 0x01 | 0x02 | 0x04
	ACT_REACTION = 0x06, // 0x02 | 0x04
	ACT_DECIDE = 0x00
// custom
};

enum ReactStates {
	REACT_PASSIVE = 0, REACT_DEFENSIVE = 1, REACT_AGGRESSIVE = 2
};

enum CommandStates {
	COMMAND_STAY = 0,
	COMMAND_FOLLOW = 1,
	COMMAND_ATTACK = 2,
	COMMAND_ABANDON = 3
};

#define UNIT_ACTION_BUTTON_ACTION(X) (uint32(X) & 0x00FFFFFF)
#define UNIT_ACTION_BUTTON_TYPE(X)   ((uint32(X) & 0xFF000000) >> 24)
#define MAX_UNIT_ACTION_BUTTON_ACTION_VALUE (0x00FFFFFF+1)
#define MAKE_UNIT_ACTION_BUTTON(A, T) (uint32(A) | (uint32(T) << 24))

struct UnitActionBarEntry {
	UnitActionBarEntry() :
			packedData(uint32(ACT_DISABLED) << 24) {
	}

	uint32 packedData;

	// helper
	ActiveStates GetType() const {
		return ActiveStates(UNIT_ACTION_BUTTON_TYPE(packedData));
	}
	uint32 GetAction() const {
		return UNIT_ACTION_BUTTON_ACTION(packedData);
	}
	bool IsActionBarForSpell() const {
		ActiveStates Type = GetType();
		return Type == ACT_DISABLED || Type == ACT_ENABLED
				|| Type == ACT_PASSIVE;
	}

	void SetActionAndType(uint32 action, ActiveStates type) {
		packedData = MAKE_UNIT_ACTION_BUTTON(action, type);
	}

	void SetType(ActiveStates type) {
		packedData =
				MAKE_UNIT_ACTION_BUTTON(UNIT_ACTION_BUTTON_ACTION(packedData), type);
	}

	void SetAction(uint32 action) {
		packedData = (packedData & 0xFF000000)
				| UNIT_ACTION_BUTTON_ACTION(action);
	}
};

typedef std::list<Player*> SharedVisionList;

enum CharmType {
	CHARM_TYPE_CHARM, CHARM_TYPE_POSSESS, CHARM_TYPE_VEHICLE, CHARM_TYPE_CONVERT,
};

typedef UnitActionBarEntry CharmSpellEntry;

enum ActionBarIndex {
	ACTION_BAR_INDEX_START = 0,
	ACTION_BAR_INDEX_PET_SPELL_START = 3,
	ACTION_BAR_INDEX_PET_SPELL_END = 7,
	ACTION_BAR_INDEX_END = 10,
};

#define MAX_UNIT_ACTION_BAR_INDEX (ACTION_BAR_INDEX_END-ACTION_BAR_INDEX_START)

struct CharmInfo {
public:
	explicit CharmInfo(Unit* unit);
	~CharmInfo();
	void RestoreState();
	uint32 GetPetNumber() const {
		return m_petnumber;
	}
	void SetPetNumber(uint32 petnumber, bool statwindow);

	void SetCommandState(CommandStates st) {
		m_CommandState = st;
	}
	CommandStates GetCommandState() const {
		return m_CommandState;
	}
	bool HasCommandState(CommandStates state) const {
		return (m_CommandState == state);
	}

	void InitPossessCreateSpells();
	void InitCharmCreateSpells();
	void InitPetActionBar();
	void InitEmptyActionBar(bool withAttack = true);

	//return true if successful
	bool AddSpellToActionBar(uint32 spellid,
			ActiveStates newstate = ACT_DECIDE);
	bool RemoveSpellFromActionBar(uint32 spell_id);
	void LoadPetActionBar(const std::string& data);
	void BuildActionBar(WorldPacket* data);
	void SetSpellAutocast(uint32 spell_id, bool state);
	void SetActionBar(uint8 index, uint32 spellOrAction, ActiveStates type) {
		PetActionBar[index].SetActionAndType(spellOrAction, type);
	}
	UnitActionBarEntry const* GetActionBarEntry(uint8 index) const {
		return &(PetActionBar[index]);
	}

	void ToggleCreatureAutocast(uint32 spellid, bool apply);

	CharmSpellEntry* GetCharmSpell(uint8 index) {
		return &(m_charmspells[index]);
	}

	void SetIsCommandAttack(bool val);
	bool IsCommandAttack();
	void SetIsAtStay(bool val);
	bool IsAtStay();
	void SetIsFollowing(bool val);
	bool IsFollowing();
	void SetIsReturning(bool val);
	bool IsReturning();
	void SaveStayPosition();
	void GetStayPosition(float &x, float &y, float &z);

private:
	Unit* m_unit;
	UnitActionBarEntry PetActionBar[MAX_UNIT_ACTION_BAR_INDEX];
	CharmSpellEntry m_charmspells[4];
	CommandStates m_CommandState;
	uint32 m_petnumber;
	bool m_barInit;

	//for restoration after charmed
	ReactStates m_oldReactState;

	bool m_isCommandAttack;
	bool m_isAtStay;
	bool m_isFollowing;
	bool m_isReturning;
	float m_stayX;
	float m_stayY;
	float m_stayZ;
};

// for clearing special attacks
#define REACTIVE_TIMER_START 4000

enum ReactiveType {
	REACTIVE_DEFENSE = 0, REACTIVE_HUNTER_PARRY = 1, REACTIVE_OVERPOWER = 2
};

#define MAX_REACTIVE 3
#define SUMMON_SLOT_PET     0
#define SUMMON_SLOT_TOTEM   1
#define MAX_TOTEM_SLOT      5
#define SUMMON_SLOT_MINIPET 5
#define SUMMON_SLOT_QUEST   6
#define MAX_SUMMON_SLOT     7

enum PlayerTotemType {
	SUMMON_TYPE_TOTEM_FIRE = 63,
	SUMMON_TYPE_TOTEM_EARTH = 81,
	SUMMON_TYPE_TOTEM_WATER = 82,
	SUMMON_TYPE_TOTEM_AIR = 83,
};

// delay time next attack to prevent client attack animation problems
#define ATTACK_DISPLAY_DELAY 200
#define MAX_PLAYER_STEALTH_DETECT_RANGE 30.0f               // max distance for detection targets by player
struct SpellProcEventEntry;
// used only privately

class Unit: public WorldObject {
public:
	typedef std::set<Unit*> AttackerSet;
	typedef std::set<Unit*> ControlList;
	typedef std::pair<uint32, uint8> spellEffectPair;
	typedef std::multimap<uint32, Aura*> AuraMap;
	typedef std::multimap<uint32, AuraApplication*> AuraApplicationMap;
	typedef std::multimap<AuraState, AuraApplication*> AuraStateAurasMap;
	typedef std::list<AuraEffect *> AuraEffectList;
	typedef std::list<Aura *> AuraList;
	typedef std::list<AuraApplication *> AuraApplicationList;
	typedef std::list<DiminishingReturn> Diminishing;
	typedef std::set<uint32> ComboPointHolderSet;

	typedef std::map<uint8, AuraApplication*> VisibleAuraMap;

	virtual ~Unit();

	UnitAI* GetAI() {
		return i_AI;
	}
	void SetAI(UnitAI* newAI) {
		i_AI = newAI;
	}

	void AddToWorld();
	void RemoveFromWorld();

	void CleanupsBeforeDelete(bool finalCleanup = true); // used in ~Creature/~Player (or before mass creature delete to remove cross-references to already deleted units)

	DiminishingLevels GetDiminishing(DiminishingGroup group);
	void IncrDiminishing(DiminishingGroup group);
	float ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,
			Unit* caster, DiminishingLevels Level, int32 limitduration);
	void ApplyDiminishingAura(DiminishingGroup group, bool apply);
	void ClearDiminishings() {
		m_Diminishing.clear();
	}

	//target dependent range checks
	uint32 GetSpellMaxRangeForTarget(Unit* target,
			const SpellRangeEntry * rangeEntry);
	uint32 GetSpellMinRangeForTarget(Unit* target,
			const SpellRangeEntry * rangeEntry);
	uint32 GetSpellRadiusForTarget(Unit* target,
			const SpellRadiusEntry * radiusEntry);

	virtual void Update(uint32 time);

	void setAttackTimer(WeaponAttackType type, uint32 time) {
		m_attackTimer[type] = time;
	}
	void resetAttackTimer(WeaponAttackType type = BASE_ATTACK);
	uint32 getAttackTimer(WeaponAttackType type) const {
		return m_attackTimer[type];
	}
	bool isAttackReady(WeaponAttackType type = BASE_ATTACK) const {
		return m_attackTimer[type] == 0;
	}
	bool haveOffhandWeapon() const;
	bool CanDualWield() const {
		return m_canDualWield;
	}
	void SetCanDualWield(bool value) {
		m_canDualWield = value;
	}
	float GetCombatReach() const {
		return m_floatValues[UNIT_FIELD_COMBATREACH];
	}
	float GetMeleeReach() const {
		float reach = m_floatValues[UNIT_FIELD_COMBATREACH];
		return reach > MIN_MELEE_REACH ? reach : MIN_MELEE_REACH;
	}
	bool IsWithinCombatRange(const Unit *obj, float dist2compare) const;
	bool IsWithinMeleeRange(const Unit *obj, float dist = MELEE_RANGE) const;
	void GetRandomContactPoint(const Unit* target, float &x, float &y, float &z,
			float distance2dMin, float distance2dMax) const;
	uint32 m_extraAttacks;
	bool m_canDualWield;

	void _addAttacker(Unit *pAttacker) // must be called only from Unit::Attack(Unit*)
			{
		m_attackers.insert(pAttacker);
	}
	void _removeAttacker(Unit *pAttacker) // must be called only from Unit::AttackStop()
			{
		m_attackers.erase(pAttacker);
	}
	Unit * getAttackerForHelper() const // If someone wants to help, who to give them
	{
		if (getVictim() != NULL)
			return getVictim();

		if (!m_attackers.empty())
			return *(m_attackers.begin());

		return NULL;
	}
	bool Attack(Unit *victim, bool meleeAttack);
	void CastStop(uint32 except_spellid = 0);
	bool AttackStop();
	void RemoveAllAttackers();
	AttackerSet const& getAttackers() const {
		return m_attackers;
	}
	bool isAttackingPlayer() const;
	Unit* getVictim() const {
		return m_attacking;
	}

	void CombatStop(bool includingCast = false);
	void CombatStopWithPets(bool includingCast = false);
	void StopAttackFaction(uint32 faction_id);
	Unit* SelectNearbyTarget(float dist = NOMINAL_MELEE_RANGE) const;
	void SendMeleeAttackStop(Unit* victim);
	void SendMeleeAttackStart(Unit* pVictim);

	bool IsVisionObscured(Unit* pVictim);

	void AddUnitState(uint32 f) {
		m_state |= f;
	}
	bool HasUnitState(const uint32 f) const {
		return (m_state & f);
	}
	void ClearUnitState(uint32 f) {
		m_state &= ~f;
	}
	bool CanFreeMove() const {
		return !HasUnitState(
				UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_IN_FLIGHT
						| UNIT_STAT_ROOT | UNIT_STAT_STUNNED
						| UNIT_STAT_DISTRACTED) && GetOwnerGUID() == 0;
	}

	uint32 HasUnitTypeMask(uint32 mask) const {
		return mask & m_unitTypeMask;
	}
	void AddUnitTypeMask(uint32 mask) {
		m_unitTypeMask |= mask;
	}
	bool isSummon() const {
		return m_unitTypeMask & UNIT_MASK_SUMMON;
	}
	bool isGuardian() const {
		return m_unitTypeMask & UNIT_MASK_GUARDIAN;
	}
	bool isPet() const {
		return m_unitTypeMask & UNIT_MASK_PET;
	}
	bool isHunterPet() const {
		return m_unitTypeMask & UNIT_MASK_HUNTER_PET;
	}
	bool isTotem() const {
		return m_unitTypeMask & UNIT_MASK_TOTEM;
	}
	bool IsVehicle() const {
		return m_unitTypeMask & UNIT_MASK_VEHICLE;
	}

	uint8 getLevel() const {
		return uint8(GetUInt32Value(UNIT_FIELD_LEVEL));
	}
	uint8 getLevelForTarget(WorldObject const* /*target*/) const {
		return getLevel();
	}
	void SetLevel(uint8 lvl);
	uint8 getRace() const {
		return GetByteValue(UNIT_FIELD_BYTES_0, 0);
	}
	uint32 getRaceMask() const {
		return 1 << (getRace() - 1);
	}
	virtual uint8 getClass() const {
		return GetByteValue(UNIT_FIELD_BYTES_0, 1);
	}
	uint32 getClassMask() const {
		return 1 << (getClass() - 1);
	}
	uint8 getGender() const {
		return GetByteValue(UNIT_FIELD_BYTES_0, 2);
	}

	float GetStat(Stats stat) const {
		return float(GetUInt32Value(UNIT_FIELD_STAT0 + stat));
	}
	void SetStat(Stats stat, int32 val) {
		SetStatInt32Value(UNIT_FIELD_STAT0 + stat, val);
	}
	uint32 GetArmor() const {
		return GetResistance(SPELL_SCHOOL_NORMAL);
	}
	void SetArmor(int32 val) {
		SetResistance(SPELL_SCHOOL_NORMAL, val);
	}

	uint32 GetResistance(SpellSchools school) const {
		return GetUInt32Value(UNIT_FIELD_RESISTANCES + school);
	}
	uint32 GetResistance(SpellSchoolMask mask) const;
	void SetResistance(SpellSchools school, int32 val) {
		SetStatInt32Value(UNIT_FIELD_RESISTANCES + school, val);
	}

	uint32 GetHealth() const {
		return GetUInt32Value(UNIT_FIELD_HEALTH);
	}
	uint32 GetMaxHealth() const {
		return GetUInt32Value(UNIT_FIELD_MAXHEALTH);
	}

	inline bool IsFullHealth() const {
		return GetHealth() == GetMaxHealth();
	}
	inline bool HealthBelowPct(int32 pct) const {
		return GetHealth() * (uint64) 100 < GetMaxHealth() * (uint64) pct;
	}
	inline bool HealthBelowPctDamaged(int32 pct, uint32 damage) const {
		return (int32(GetHealth()) - damage) * (int64) 100
				< GetMaxHealth() * (int64) pct;
	}
	inline bool HealthAbovePct(int32 pct) const {
		return GetHealth() * (uint64) 100 > GetMaxHealth() * (uint64) pct;
	}
	inline bool HealthAbovePctHealed(int32 pct, uint32 heal) const { return (GetHealth() + heal) * uint64(100) > GetMaxHealth() * uint64(pct); }
	inline float GetHealthPct() const {
		return GetMaxHealth() ? 100.f * GetHealth() / GetMaxHealth() : 0.0f;
	}
	inline uint32 CountPctFromMaxHealth(int32 pct) const {
		return uint32(float(pct) * GetMaxHealth() / 100.0f);
	}

	void SetHealth(uint32 val);
	void SetMaxHealth(uint32 val);
	inline void SetFullHealth() {
		SetHealth(GetMaxHealth());
	}
	int32 ModifyHealth(int32 val);
	int32 GetHealthGain(int32 dVal);

	Powers getPowerType() const {
		return Powers(GetByteValue(UNIT_FIELD_BYTES_0, 3));
	}
	void setPowerType(Powers power);
	uint32 GetPower(Powers power) const {
		return GetUInt32Value(UNIT_FIELD_POWER1 + power);
	}
	uint32 GetMaxPower(Powers power) const {
		return GetUInt32Value(UNIT_FIELD_MAXPOWER1 + power);
	}
	void SetPower(Powers power, uint32 val);
	void SetMaxPower(Powers power, uint32 val);
	// returns the change in power
	int32 ModifyPower(Powers power, int32 val);
	int32 ModifyPowerPct(Powers power, float pct, bool apply = true);

	uint32 GetAttackTime(WeaponAttackType att) const {
		float f_BaseAttackTime = GetFloatValue(UNIT_FIELD_BASEATTACKTIME + att)
				/ m_modAttackSpeedPct[att];
		return (uint32) f_BaseAttackTime;
	}

	void SetAttackTime(WeaponAttackType att, uint32 val) {
		SetFloatValue(UNIT_FIELD_BASEATTACKTIME + att,
				val * m_modAttackSpeedPct[att]);
	}
	void ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply);
	void ApplyCastTimePercentMod(float val, bool apply);

	SheathState GetSheath() const {
		return SheathState(GetByteValue(UNIT_FIELD_BYTES_2, 0));
	}
	virtual void SetSheath(SheathState sheathed) {
		SetByteValue(UNIT_FIELD_BYTES_2, 0, sheathed);
	}

	// faction template id
	uint32 getFaction() const {
		return GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE);
	}
	void setFaction(uint32 faction) {
		SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction);
	}
	FactionTemplateEntry const* getFactionTemplateEntry() const;
    ReputationRank GetReactionTo(Unit const* target) const;
    ReputationRank static GetFactionReactionTo(FactionTemplateEntry const* factionTemplateEntry, Unit const* target);
	bool IsHostileTo(Unit const* unit) const;
	bool IsHostileToPlayers() const;
	bool IsFriendlyTo(Unit const* unit) const;
	bool IsNeutralToAll() const;
	bool IsInPartyWith(Unit const* unit) const;
	bool IsInRaidWith(Unit const* unit) const;
	void GetPartyMemberInDist(std::list<Unit*> &units, float dist);
	void GetPartyMembers(std::list<Unit*> &units);
	void GetRaidMember(std::list<Unit*> &units, float dist);
	bool IsContestedGuard() const {
		if (FactionTemplateEntry const* entry = getFactionTemplateEntry())
			return entry->IsContestedGuardFaction();

		return false;
	}
	bool IsPvP() const {
		return HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP);
	}
	void SetPvP(bool state) {
		if (state)
			SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP);
		else
			RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP);
	}
	uint32 GetCreatureType() const;
	uint32 GetCreatureTypeMask() const {
		uint32 creatureType = GetCreatureType();
		return (creatureType >= 1) ? (1 << (creatureType - 1)) : 0;
	}

	uint8 getStandState() const {
		return GetByteValue(UNIT_FIELD_BYTES_1, 0);
	}
	bool IsSitState() const;
	bool IsStandState() const;
	void SetStandState(uint8 state);

	void SetStandFlags(uint8 flags) {
		SetByteFlag(UNIT_FIELD_BYTES_1, 2, flags);
	}
	void RemoveStandFlags(uint8 flags) {
		RemoveByteFlag(UNIT_FIELD_BYTES_1, 2, flags);
	}

	bool IsMounted() const {
		return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT);
	}
	uint32 GetMountID() const {
		return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID);
	}
	void Mount(uint32 mount, uint32 vehicleId = 0, uint32 creatureEntry = 0);
	void Unmount();

	uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const {
		return (target ? getLevelForTarget(target) : getLevel()) * 5;
	}
	void DealDamageMods(Unit *pVictim, uint32 &damage, uint32* absorb);
	uint32 DealDamage(Unit *pVictim, uint32 damage,
			CleanDamage const* cleanDamage = NULL, DamageEffectType damagetype =
					DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask =
					SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *spellProto =
					NULL, bool durabilityLoss = true);
	void Kill(Unit *pVictim, bool durabilityLoss = true);
	int32 DealHeal(Unit *pVictim, uint32 addhealth);

	void ProcDamageAndSpell(Unit *pVictim, uint32 procAttacker,
			uint32 procVictim, uint32 procEx, uint32 amount,
			WeaponAttackType attType = BASE_ATTACK,
			SpellEntry const *procSpell = NULL, SpellEntry const * procAura =
					NULL);
	void ProcDamageAndSpellFor(bool isVictim, Unit * pTarget, uint32 procFlag,
			uint32 procExtra, WeaponAttackType attType,
			SpellEntry const * procSpell, uint32 damage,
			SpellEntry const * procAura = NULL);

	void HandleEmoteCommand(uint32 anim_id);
	void AttackerStateUpdate(Unit *pVictim, WeaponAttackType attType =
			BASE_ATTACK, bool extra = false);

	//float MeleeMissChanceCalc(const Unit *pVictim, WeaponAttackType attType) const;

	void CalculateMeleeDamage(Unit *pVictim, uint32 damage,
			CalcDamageInfo *damageInfo, WeaponAttackType attackType =
					BASE_ATTACK);
	void DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss);

	void CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo,
			int32 damage, SpellEntry const *spellInfo,
			WeaponAttackType attackType = BASE_ATTACK, bool crit = false);
	void DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss);

	// player or player's pet resilience (-1%), cap 100%
	uint32 GetPlayerDamageReduction(uint32 damage) const {
		return GetCombatRatingDamageReduction(CR_RESILIENCE_PLAYER_DAMAGE_TAKEN,
				1.0f, 100.0f, damage);
	}

	void ApplyResilience(const Unit * pVictim, int32 * damage) const;

	float MeleeSpellMissChance(const Unit *pVictim, WeaponAttackType attType,
			int32 skillDiff, uint32 spellId) const;
	SpellMissInfo MeleeSpellHitResult(Unit *pVictim, SpellEntry const *spell);
	SpellMissInfo MagicSpellHitResult(Unit *pVictim, SpellEntry const *spell);
	SpellMissInfo SpellHitResult(Unit *pVictim, SpellEntry const *spell,
			bool canReflect = false);

	float GetUnitDodgeChance() const;
	float GetUnitParryChance() const;
	float GetUnitBlockChance() const;
	float GetUnitCriticalChance(WeaponAttackType attackType,
			const Unit *pVictim) const;
	int32 GetMechanicResistChance(const SpellEntry *spell);
	bool CanUseAttackType(uint8 attacktype) const {
		switch (attacktype) {
		case BASE_ATTACK:
			return !HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
		case OFF_ATTACK:
			return !HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISARM_OFFHAND);
		case RANGED_ATTACK:
			return !HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISARM_RANGED);
		}
		return true;
	}

	virtual uint32 GetShieldBlockValue() const =0;
	uint32 GetUnitMeleeSkill(Unit const* target = NULL) const {
		return (target ? getLevelForTarget(target) : getLevel()) * 5;
	}
	uint32 GetDefenseSkillValue(Unit const* target = NULL) const;
	uint32 GetWeaponSkillValue(WeaponAttackType attType, Unit const* target =
			NULL) const;
	float GetWeaponProcChance() const;
	float GetPPMProcChance(uint32 WeaponSpeed, float PPM,
			const SpellEntry * spellProto) const;

	MeleeHitOutcome RollMeleeOutcomeAgainst(const Unit *pVictim,
			WeaponAttackType attType) const;
	MeleeHitOutcome RollMeleeOutcomeAgainst(const Unit *pVictim,
			WeaponAttackType attType, int32 crit_chance, int32 miss_chance,
			int32 dodge_chance, int32 parry_chance, int32 block_chance) const;

	bool isVendor() const {
		return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR);
	}
	bool isTrainer() const {
		return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TRAINER);
	}
	bool isQuestGiver() const {
		return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
	}
	bool isGossip() const {
		return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
	}
	bool isTaxi() const {
		return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_FLIGHTMASTER);
	}
	bool isGuildMaster() const {
		return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PETITIONER);
	}
	bool isBattleMaster() const {
		return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BATTLEMASTER);
	}
	bool isBanker() const {
		return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BANKER);
	}
	bool isInnkeeper() const {
		return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_INNKEEPER);
	}
	bool isSpiritHealer() const {
		return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER);
	}
	bool isSpiritGuide() const {
		return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITGUIDE);
	}
	bool isTabardDesigner() const {
		return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TABARDDESIGNER);
	}
	bool isAuctioner() const {
		return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_AUCTIONEER);
	}
	bool isArmorer() const {
		return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_REPAIR);
	}
	bool isServiceProvider() const {
		return HasFlag(
				UNIT_NPC_FLAGS,
				UNIT_NPC_FLAG_VENDOR | UNIT_NPC_FLAG_TRAINER
						| UNIT_NPC_FLAG_FLIGHTMASTER | UNIT_NPC_FLAG_PETITIONER
						| UNIT_NPC_FLAG_BATTLEMASTER | UNIT_NPC_FLAG_BANKER
						| UNIT_NPC_FLAG_INNKEEPER | UNIT_NPC_FLAG_SPIRITHEALER
						| UNIT_NPC_FLAG_SPIRITGUIDE
						| UNIT_NPC_FLAG_TABARDDESIGNER
						| UNIT_NPC_FLAG_AUCTIONEER);
	}
	bool isSpiritService() const {
		return HasFlag(UNIT_NPC_FLAGS,
				UNIT_NPC_FLAG_SPIRITHEALER | UNIT_NPC_FLAG_SPIRITGUIDE);
	}

	bool isInFlight() const {
		return HasUnitState(UNIT_STAT_IN_FLIGHT);
	}

	bool isInCombat() const {
		return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
	}
	void CombatStart(Unit* target, bool initialAggro = true);
	void SetInCombatState(bool PvP, Unit* enemy = NULL);
	void SetInCombatWith(Unit* enemy);
	void ClearInCombat();
	uint32 GetCombatTimer() const {
		return m_CombatTimer;
	}

	bool HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName,
			uint32 familyFlags) const;
	bool virtual HasSpell(uint32 /*spellID*/) const {
		return false;
	}

	bool HasStealthAura() const {
		return HasAuraType(SPELL_AURA_MOD_STEALTH);
	}
	bool HasInvisibilityAura() const {
		return HasAuraType(SPELL_AURA_MOD_INVISIBILITY);
	}
	bool isFeared() const {
		return HasAuraType(SPELL_AURA_MOD_FEAR);
	}
	bool isInRoots() const {
		return HasAuraType(SPELL_AURA_MOD_ROOT);
	}
	bool IsPolymorphed() const;

	bool isFrozen() const;

	bool isTargetableForAttack(bool checkFakeDeath = true) const;
    bool IsValidAttackTarget(Unit const* target) const;
    bool _IsValidAttackTarget(Unit const* target, SpellEntry const* bySpell) const;
	bool isAttackableByAOE(bool requireDeadTarget = false) const;
	bool canAttack(Unit const* target, bool force = true) const;
	virtual bool IsInWater() const;
	virtual bool IsUnderWater() const;
	bool isInAccessiblePlaceFor(Creature const* c) const;

	void SendHealSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage,
			uint32 OverHeal, uint32 Absorb, bool critical = false);
	int32 HealBySpell(Unit * pVictim, SpellEntry const * spellInfo,
			uint32 addHealth, bool critical = false);
	void SendEnergizeSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage,
			Powers powertype);
	void EnergizeBySpell(Unit *pVictim, uint32 SpellID, uint32 Damage,
			Powers powertype);
	uint32 SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage);
	void CastSpell(Unit* Victim, uint32 spellId, bool triggered,
			Item *castItem = NULL, AuraEffect const * triggeredByAura = NULL,
			uint64 originalCaster = 0);
	void CastSpell(Unit* Victim, SpellEntry const *spellInfo, bool triggered,
			Item *castItem = NULL, AuraEffect const * triggeredByAura = NULL,
			uint64 originalCaster = 0);
	void CastSpell(float x, float y, float z, uint32 spellId, bool triggered,
			Item *castItem = NULL, AuraEffect const * triggeredByAura = NULL,
			uint64 originalCaster = 0, Unit* originalVictim = 0);
	void CastCustomSpell(Unit* Victim, uint32 spellId, int32 const* bp0,
			int32 const* bp1, int32 const* bp2, bool triggered, Item *castItem =
					NULL, AuraEffect const * triggeredByAura = NULL,
			uint64 originalCaster = 0);
	void CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value,
			Unit* Victim = NULL, bool triggered = true, Item *castItem = NULL,
			AuraEffect const * triggeredByAura = NULL,
			uint64 originalCaster = 0);
	void CastCustomSpell(uint32 spellId, CustomSpellValues const &value,
			Unit* Victim = NULL, bool triggered = true, Item *castItem = NULL,
			AuraEffect const * triggeredByAura = NULL,
			uint64 originalCaster = 0);
	void CastSpell(GameObject *go, uint32 spellId, bool triggered,
			Item *castItem = NULL, AuraEffect* triggeredByAura = NULL,
			uint64 originalCaster = 0);
	Aura * AddAura(uint32 spellId, Unit *target);
	Aura * AddAura(SpellEntry const *spellInfo, uint8 effMask, Unit *target);
	void SetAuraStack(uint32 spellId, Unit *target, uint32 stack);

	bool IsDamageToThreatSpell(SpellEntry const * spellInfo) const;

	void DeMorph();

	void SendAttackStateUpdate(CalcDamageInfo *damageInfo);
	void SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType,
			SpellSchoolMask damageSchoolMask, uint32 Damage,
			uint32 AbsorbDamage, uint32 Resist, VictimState TargetState,
			uint32 BlockedAmount);
	void SendSpellNonMeleeDamageLog(SpellNonMeleeDamage *log);
	void SendSpellNonMeleeDamageLog(Unit *target, uint32 SpellID, uint32 Damage,
			SpellSchoolMask damageSchoolMask, uint32 AbsorbedDamage,
			uint32 Resist, bool PhysicalDamage, uint32 Blocked,
			bool CriticalHit = false);
	void SendPeriodicAuraLog(SpellPeriodicAuraLogInfo *pInfo);
	void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo);
	void SendSpellDamageImmune(Unit *target, uint32 spellId);

	void NearTeleportTo(float x, float y, float z, float orientation,
			bool casting = false);
	virtual bool SetPosition(float x, float y, float z, float ang,
			bool teleport = false);
	// returns true if unit's position really changed
	bool SetPosition(const Position &pos, bool teleport = false) {
		return SetPosition(pos.GetPositionX(), pos.GetPositionY(),
				pos.GetPositionZ(), pos.GetOrientation(), teleport);
	}

    virtual bool UpdatePosition(float x, float y, float z, float ang, bool teleport = false);
    // returns true if unit's position really changed
    bool UpdatePosition(const Position &pos, bool teleport = false) { return UpdatePosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teleport); }
	void KnockbackFrom(float x, float y, float speedXY, float speedZ);
	void JumpTo(float speedXY, float speedZ, bool forward = true);
	void JumpTo(WorldObject *obj, float speedZ);

	void SetFacing(float ori, WorldObject* obj = NULL);
	void SendMonsterStop(bool on_death = false);
	void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 Time, Player* player = NULL);
	void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 MoveFlags, uint32 time, float speedZ, Player *player = NULL);
	void SendMonsterMove(MonsterMoveData const& moveData, Player* receiver = NULL);
	void SendMonsterMoveTransport(Unit *vehicleOwner);
	void SendMonsterMoveWithSpeed(float x, float y, float z,
			uint32 transitTime = 0, Player* player = NULL);
	void SendMonsterMoveWithSpeedToCurrentDestination(Player* player = NULL);
	void SendMovementFlagUpdate();

	template<typename PathElem, typename PathNode>
	void SendMonsterMoveByPath(Path<PathElem, PathNode> const& path
			, uint32 start, uint32 end);

	void SendChangeCurrentVictimOpcode(HostileReference* pHostileReference);
	void SendClearThreatListOpcode();
	void SendRemoveFromThreatListOpcode(HostileReference* pHostileReference);
	void SendThreatListUpdate();

	void BuildHeartBeatMsg(WorldPacket *data) const;
	
    void SendClearTarget();	

	bool isAlive() const {
		return (m_deathState == ALIVE);
	}
	;
	bool isDying() const {
		return (m_deathState == JUST_DIED);
	}
	;
	bool isDead() const {
		return (m_deathState == DEAD || m_deathState == CORPSE);
	}
	;
	DeathState getDeathState() {
		return m_deathState;
	}
	;
	virtual void setDeathState(DeathState s); // overwrited in Creature/Player/Pet

	uint64 GetOwnerGUID() const {
		return GetUInt64Value(UNIT_FIELD_SUMMONEDBY);
	}
	uint64 GetCreatorGUID() const {
		return GetUInt64Value(UNIT_FIELD_CREATEDBY);
	}
	void SetCreatorGUID(uint64 creator) {
		SetUInt64Value(UNIT_FIELD_CREATEDBY, creator);
	}
	uint64 GetMinionGUID() const {
		return GetUInt64Value(UNIT_FIELD_SUMMON);
	}
	void SetMinionGUID(uint64 guid) {
		SetUInt64Value(UNIT_FIELD_SUMMON, guid);
	}
	uint64 GetCharmerGUID() const {
		return GetUInt64Value(UNIT_FIELD_CHARMEDBY);
	}
	void SetCharmerGUID(uint64 owner) {
		SetUInt64Value(UNIT_FIELD_CHARMEDBY, owner);
	}
	uint64 GetCharmGUID() const {
		return GetUInt64Value(UNIT_FIELD_CHARM);
	}
	void SetPetGUID(uint64 guid) {
		m_SummonSlot[SUMMON_SLOT_PET] = guid;
	}
	uint64 GetPetGUID() const {
		return m_SummonSlot[SUMMON_SLOT_PET];
	}
	void SetCritterGUID(uint64 guid) {
		SetUInt64Value(UNIT_FIELD_CRITTER, guid);
	}
	uint64 GetCritterGUID() const {
		return GetUInt64Value(UNIT_FIELD_CRITTER);
	}

	bool IsControlledByPlayer() const {
		return m_ControlledByPlayer;
	}
	uint64 GetCharmerOrOwnerGUID() const {
		return GetCharmerGUID() ? GetCharmerGUID() : GetOwnerGUID();
	}
	uint64 GetCharmerOrOwnerOrOwnGUID() const {
		if (uint64 guid = GetCharmerOrOwnerGUID())
			return guid;
		return GetGUID();
	}
	bool isCharmedOwnedByPlayerOrPlayer() const {
		return IS_PLAYER_GUID(GetCharmerOrOwnerOrOwnGUID());
	}

	Player* GetSpellModOwner() const;

	Unit* GetOwner() const;
	Guardian *GetGuardianPet() const;
	Minion *GetFirstMinion() const;
	Unit* GetCharmer() const;
	Unit* GetCharm() const;
	Unit* GetCharmerOrOwner() const {
		return GetCharmerGUID() ? GetCharmer() : GetOwner();
	}
	Unit* GetCharmerOrOwnerOrSelf() const {
		if (Unit *u = GetCharmerOrOwner())
			return u;

		return (Unit*) this;
	}
	Player* GetCharmerOrOwnerPlayerOrPlayerItself() const;
	Player* GetAffectingPlayer() const;

	void SetMinion(Minion *minion, bool apply, PetSlot slot);
	void GetAllMinionsByEntry(std::list<Unit*>& Minions, uint32 entry);
	void RemoveAllMinionsByEntry(uint32 entry);
	void SetCharm(Unit* target, bool apply);
	Unit* GetNextRandomRaidMemberOrPet(float radius);
	bool SetCharmedBy(Unit* charmer, CharmType type,
			AuraApplication const * aurApp = NULL);
	void RemoveCharmedBy(Unit* charmer);
	void RestoreFaction();

	ControlList m_Controlled;
	Unit* GetFirstControlled() const;
	void RemoveAllControlled();

	bool isCharmed() const {
		return GetCharmerGUID() != 0;
	}
	bool isPossessed() const {
		return HasUnitState(UNIT_STAT_POSSESSED);
	}
	bool isPossessedByPlayer() const {
		return HasUnitState(UNIT_STAT_POSSESSED)
				&& IS_PLAYER_GUID(GetCharmerGUID());
	}
	bool isPossessing() const {
		if (Unit *u = GetCharm())
			return u->isPossessed();
		else
			return false;
	}
	bool isPossessing(Unit* u) const {
		return u->isPossessed() && GetCharmGUID() == u->GetGUID();
	}

	CharmInfo* GetCharmInfo() {
		return m_charmInfo;
	}
	CharmInfo* InitCharmInfo();
	void DeleteCharmInfo();
	void UpdateCharmAI();
	//Player * GetMoverSource() const;
	Player * m_movedPlayer;
	SharedVisionList const& GetSharedVisionList() {
		return m_sharedVision;
	}
	void AddPlayerToVision(Player* plr);
	void RemovePlayerFromVision(Player* plr);
	bool HasSharedVision() const {
		return !m_sharedVision.empty();
	}
	void RemoveBindSightAuras();
	void RemoveCharmAuras();

	Pet* CreateTamedPetFrom(Creature* creatureTarget, uint32 spell_id = 0);
	Pet* CreateTamedPetFrom(uint32 creatureEntry, uint32 spell_id = 0);
	bool InitTamedPet(Pet * pet, uint8 level, uint32 spell_id);

	// aura apply/remove helpers - you should better not use these
	void _AddAura(UnitAura * aura, Unit * caster);
	AuraApplication * _CreateAuraApplication(Aura * aura, uint8 effMask);
	void _ApplyAuraEffect(Aura * aura, uint8 effIndex);
	void _ApplyAura(AuraApplication * aurApp, uint8 effMask);
	void _UnapplyAura(AuraApplicationMap::iterator &i,
			AuraRemoveMode removeMode);
	void _UnapplyAura(AuraApplication * aurApp, AuraRemoveMode removeMode);
	void _RemoveNoStackAuraApplicationsDueToAura(Aura * aura);
	void _RemoveNoStackAurasDueToAura(Aura * aura);
	bool _IsNoStackAuraDueToAura(Aura * appliedAura, Aura * existingAura) const;
	void _RegisterAuraEffect(AuraEffect * aurEff, bool apply);

	// m_ownedAuras container management
	AuraMap & GetOwnedAuras() {
		return m_ownedAuras;
	}
	AuraMap const& GetOwnedAuras() const {
		return m_ownedAuras;
	}

	void RemoveOwnedAura(AuraMap::iterator &i, AuraRemoveMode removeMode =
			AURA_REMOVE_BY_DEFAULT);
	void RemoveOwnedAura(uint32 spellId, uint64 caster = 0,
			uint8 reqEffMask = 0, AuraRemoveMode removeMode =
					AURA_REMOVE_BY_DEFAULT);
	void RemoveOwnedAura(Aura * aura, AuraRemoveMode removeMode =
			AURA_REMOVE_BY_DEFAULT);

	Aura * GetOwnedAura(uint32 spellId, uint64 casterGUID = 0,
			uint64 itemCasterGUID = 0, uint8 reqEffMask = 0,
			Aura* except = NULL) const;

	// m_appliedAuras container management
	AuraApplicationMap & GetAppliedAuras() {
		return m_appliedAuras;
	}
	AuraApplicationMap const& GetAppliedAuras() const {
		return m_appliedAuras;
	}

	void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode =
			AURA_REMOVE_BY_DEFAULT);
	void RemoveAura(uint32 spellId, uint64 caster = 0, uint8 reqEffMask = 0,
			AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
	void RemoveAura(AuraApplication * aurApp, AuraRemoveMode mode =
			AURA_REMOVE_BY_DEFAULT);
	void RemoveAura(Aura * aur, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);

	void RemoveAurasDueToSpell(uint32 spellId, uint64 caster = NULL,
			uint8 reqEffMask = 0, AuraRemoveMode removeMode =
					AURA_REMOVE_BY_DEFAULT);
	void RemoveAuraFromStack(uint32 spellId, uint64 caster = NULL,
			AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
	inline void RemoveAuraFromStack(AuraMap::iterator &iter,
			AuraRemoveMode removeMode);
	void RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID,
			Unit *dispeller);
	void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID,
			Unit *stealer);
	void RemoveAurasDueToItemSpell(Item* castItem, uint32 spellId);
	void RemoveAurasByType(AuraType auraType, uint64 casterGUID = 0,
			Aura * except = NULL, bool negative = true, bool positive = true);
	void RemoveNotOwnSingleTargetAuras(uint32 newPhase = 0x0);
	void RemoveAurasWithInterruptFlags(uint32 flag, uint32 except = NULL);
	void RemoveAurasWithAttribute(uint32 flags);
	void RemoveAurasWithFamily(SpellFamilyNames family, uint32 familyFlag1,
			uint32 familyFlag2, uint32 familyFlag3, uint64 casterGUID);
	void RemoveAurasWithMechanic(uint32 mechanic_mask,
			AuraRemoveMode removemode = AURA_REMOVE_BY_DEFAULT, uint32 except =
					0, int32 count = 0);
	void RemoveMovementImpairingAuras();

	void RemoveAreaAurasDueToLeaveWorld();
	void RemoveAllAuras();
	void RemoveArenaAuras(bool onleave = false);
	void RemoveAllAurasOnDeath();
	void RemoveAllAurasRequiringDeadTarget();
	void DelayOwnedAuras(uint32 spellId, uint64 caster, int32 delaytime);

	void _RemoveAllAuraStatMods();
	void _ApplyAllAuraStatMods();

	AuraEffectList const& GetAuraEffectsByType(AuraType type) const {
		return m_modAuras[type];
	}
	AuraList & GetSingleCastAuras() {
		return m_scAuras;
	}
	AuraList const& GetSingleCastAuras() const {
		return m_scAuras;
	}

	AuraEffect * GetAuraEffect(uint32 spellId, uint8 effIndex,
			uint64 casterGUID = 0) const;
	AuraEffect * GetAuraEffectOfRankedSpell(uint32 spellId, uint8 effIndex,
			uint64 casterGUID = 0) const;
	AuraEffect * GetAuraEffect(AuraType type, SpellFamilyNames name,
			uint32 iconId, uint8 effIndex) const; // spell mustn't have familyflags
	AuraEffect * GetAuraEffect(AuraType type, SpellFamilyNames family,
			uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3,
			uint64 casterGUID = 0);
	inline AuraEffect* GetDummyAuraEffect(SpellFamilyNames name, uint32 iconId,
			uint8 effIndex) const {
		return GetAuraEffect(SPELL_AURA_DUMMY, name, iconId, effIndex);
	}

	AuraApplication * GetAuraApplication(uint32 spellId, uint64 casterGUID = 0,
			uint64 itemCasterGUID = 0, uint8 reqEffMask = 0,
			AuraApplication * except = NULL) const;
	Aura * GetAura(uint32 spellId, uint64 casterGUID = 0,
			uint64 itemCasterGUID = 0, uint8 reqEffMask = 0) const;

	AuraApplication * GetAuraApplicationOfRankedSpell(uint32 spellId,
			uint64 casterGUID = 0, uint64 itemCasterGUID = 0, uint8 reqEffMask =
					0, AuraApplication * except = NULL) const;
	Aura * GetAuraOfRankedSpell(uint32 spellId, uint64 casterGUID = 0,
			uint64 itemCasterGUID = 0, uint8 reqEffMask = 0) const;

	bool HasAuraEffect(uint32 spellId, uint8 effIndex, uint64 caster = 0) const;
	uint32 GetAuraCount(uint32 spellId) const;
	bool HasAura(uint32 spellId, uint64 casterGUID = 0, uint64 itemCasterGUID =
			0, uint8 reqEffMask = 0) const;
	bool HasAuraType(AuraType auraType) const;
	bool HasAuraTypeWithCaster(AuraType auratype, uint64 caster) const;
	bool HasAuraTypeWithMiscvalue(AuraType auratype, int32 miscvalue) const;
	bool HasAuraTypeWithAffectMask(AuraType auratype,
			SpellEntry const * affectedSpell) const;
	bool HasAuraTypeWithValue(AuraType auratype, int32 value) const;
	bool HasNegativeAuraWithInterruptFlag(uint32 flag, uint64 guid = 0);
	bool HasNegativeAuraWithAttribute(uint32 flag, uint64 guid = 0);

	AuraEffect * IsScriptOverriden(SpellEntry const * spell,
			int32 script) const;
	uint32 GetDiseasesByCaster(uint64 casterGUID, bool remove = false);
	uint32 GetDoTsByCaster(uint64 casterGUID) const;

	int32 GetTotalAuraModifier(AuraType auratype) const;
	float GetTotalAuraMultiplier(AuraType auratype) const;
	int32 GetMaxPositiveAuraModifier(AuraType auratype);
	int32 GetMaxNegativeAuraModifier(AuraType auratype) const;

	int32 GetTotalAuraModifierByMiscMask(AuraType auratype,
			uint32 misc_mask) const;
	float GetTotalAuraMultiplierByMiscMask(AuraType auratype,
			uint32 misc_mask) const;
	int32 GetMaxPositiveAuraModifierByMiscMask(AuraType auratype,
			uint32 misc_mask, const AuraEffect* except = NULL) const;
	int32 GetMaxNegativeAuraModifierByMiscMask(AuraType auratype,
			uint32 misc_mask) const;

	int32 GetTotalAuraModifierByMiscValue(AuraType auratype,
			int32 misc_value) const;
	float GetTotalAuraMultiplierByMiscValue(AuraType auratype,
			int32 misc_value) const;
	int32 GetMaxPositiveAuraModifierByMiscValue(AuraType auratype,
			int32 misc_value) const;
	int32 GetMaxNegativeAuraModifierByMiscValue(AuraType auratype,
			int32 misc_value) const;

	int32 GetTotalAuraModifierByAffectMask(AuraType auratype,
			SpellEntry const * affectedSpell) const;
	float GetTotalAuraMultiplierByAffectMask(AuraType auratype,
			SpellEntry const * affectedSpell) const;
	int32 GetMaxPositiveAuraModifierByAffectMask(AuraType auratype,
			SpellEntry const * affectedSpell) const;
	int32 GetMaxNegativeAuraModifierByAffectMask(AuraType auratype,
			SpellEntry const * affectedSpell) const;

	float GetResistanceBuffMods(SpellSchools school, bool positive) const {
		return GetFloatValue(
				positive ?
						UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + school :
						UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + school);
	}
	void SetResistanceBuffMods(SpellSchools school, bool positive, float val) {
		SetFloatValue(
				positive ?
						UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + school :
						UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + school, val);
	}
	void ApplyResistanceBuffModsMod(SpellSchools school, bool positive,
			float val, bool apply) {
		ApplyModSignedFloatValue(
				positive ?
						UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + school :
						UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + school, val,
				apply);
	}
	void ApplyResistanceBuffModsPercentMod(SpellSchools school, bool positive,
			float val, bool apply) {
		ApplyPercentModFloatValue(
				positive ?
						UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + school :
						UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + school, val,
				apply);
	}
	void InitStatBuffMods() {
		for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i)
			SetFloatValue(UNIT_FIELD_POSSTAT0 + i, 0);
		for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i)
			SetFloatValue(UNIT_FIELD_NEGSTAT0 + i, 0);
	}
	void ApplyStatBuffMod(Stats stat, float val, bool apply) {
		ApplyModSignedFloatValue(
				(val > 0 ?
						UNIT_FIELD_POSSTAT0 + stat : UNIT_FIELD_NEGSTAT0 + stat),
				val, apply);
	}
	void ApplyStatPercentBuffMod(Stats stat, float val, bool apply) {
		ApplyPercentModFloatValue(UNIT_FIELD_POSSTAT0 + stat, val, apply);
		ApplyPercentModFloatValue(UNIT_FIELD_NEGSTAT0 + stat, val, apply);
	}
	void SetCreateStat(Stats stat, float val) {
		m_createStats[stat] = val;
	}
	void SetCreateHealth(uint32 val) {
		SetUInt32Value(UNIT_FIELD_BASE_HEALTH, val);
	}
	uint32 GetCreateHealth() const {
		return GetUInt32Value(UNIT_FIELD_BASE_HEALTH);
	}
	void SetCreateMana(uint32 val) {
		SetUInt32Value(UNIT_FIELD_BASE_MANA, val);
	}
	uint32 GetCreateMana() const {
		return GetUInt32Value(UNIT_FIELD_BASE_MANA);
	}
	uint32 GetCreatePowers(Powers power) const;
	float GetPosStat(Stats stat) const {
		return GetFloatValue(UNIT_FIELD_POSSTAT0 + stat);
	}
	float GetNegStat(Stats stat) const {
		return GetFloatValue(UNIT_FIELD_NEGSTAT0 + stat);
	}
	float GetCreateStat(Stats stat) const {
		return m_createStats[stat];
	}

	void SetCurrentCastedSpell(Spell * pSpell);
	virtual void ProhibitSpellScholl(SpellSchoolMask /*idSchoolMask*/,
			uint32 /*unTimeMs*/) {
	}
	void InterruptSpell(CurrentSpellTypes spellType, bool withDelayed = true,
			bool withInstant = true);
	void FinishSpell(CurrentSpellTypes spellType, bool ok = true);

	// set withDelayed to true to account delayed spells as casted
	// delayed+channeled spells are always accounted as casted
	// we can skip channeled or delayed checks using flags
	bool IsNonMeleeSpellCasted(bool withDelayed, bool skipChanneled = false,
			bool skipAutorepeat = false, bool isAutoshoot = false,
			bool skipInstant = true) const;

	bool CanCastWhileWalking(const SpellEntry * const sp);

	// set withDelayed to true to interrupt delayed spells too
	// delayed+channeled spells are always interrupted
	void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid = 0,
			bool withInstant = true);

	Spell* GetCurrentSpell(CurrentSpellTypes spellType) const {
		return m_currentSpells[spellType];
	}
	Spell* GetCurrentSpell(uint32 spellType) const {
		return m_currentSpells[spellType];
	}
	Spell* FindCurrentSpellBySpellId(uint32 spell_id) const;
	int32 GetCurrentSpellCastTime(uint32 spell_id) const;

	uint32 m_addDmgOnce;
	uint64 m_SummonSlot[MAX_SUMMON_SLOT];
	uint64 m_ObjectSlot[4];

	ShapeshiftForm GetShapeshiftForm() const {
		return ShapeshiftForm(GetByteValue(UNIT_FIELD_BYTES_2, 3));
	}
	void SetShapeshiftForm(ShapeshiftForm form) {
		SetByteValue(UNIT_FIELD_BYTES_2, 3, form);

		// force update as too quick shapeshifting and back
		// causes the value to stay the same serverside
		// causes issues clientside (player gets stuck)
		ForceValuesUpdateAtIndex(UNIT_FIELD_BYTES_2);
	}

	inline bool IsInFeralForm() const {
		ShapeshiftForm form = GetShapeshiftForm();
		return form == FORM_CAT || form == FORM_BEAR || form == FORM_DIREBEAR;
	}

	inline bool IsInDisallowedMountForm() const {
		ShapeshiftForm form = GetShapeshiftForm();
		return form != FORM_NONE && form != FORM_BATTLESTANCE
				&& form != FORM_BERSERKERSTANCE && form != FORM_DEFENSIVESTANCE
				&& form != FORM_SHADOW && form != FORM_STEALTH;
	}

	float m_modMeleeHitChance;
	float m_modRangedHitChance;
	float m_modSpellHitChance;
	int32 m_baseSpellCritChance;

	float m_threatModifier[MAX_SPELL_SCHOOL];
	float m_modAttackSpeedPct[3];

	// Event handler
	EventProcessor m_Events;

	// stat system
	bool HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType,
			float amount, bool apply);
	void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType,
			float value) {
		m_auraModifiersGroup[unitMod][modifierType] = value;
	}
	float GetModifierValue(UnitMods unitMod,
			UnitModifierType modifierType) const;
	float GetTotalStatValue(Stats stat) const;
	float GetTotalAuraModValue(UnitMods unitMod) const;
	SpellSchools GetSpellSchoolByAuraGroup(UnitMods unitMod) const;
	Stats GetStatByAuraGroup(UnitMods unitMod) const;
	Powers GetPowerTypeByAuraGroup(UnitMods unitMod) const;
	bool CanModifyStats() const {
		return m_canModifyStats;
	}
	void SetCanModifyStats(bool modifyStats) {
		m_canModifyStats = modifyStats;
	}
	virtual bool UpdateStats(Stats stat) = 0;
	virtual bool UpdateAllStats() = 0;
	virtual void UpdateResistances(uint32 school) = 0;
	virtual void UpdateArmor() = 0;
	virtual void UpdateMaxHealth() = 0;
	virtual void UpdateMaxPower(Powers power) = 0;
	virtual void UpdateAttackPowerAndDamage(bool ranged = false) = 0;
	virtual void UpdateDamagePhysical(WeaponAttackType attType) = 0;
	float GetTotalAttackPowerValue(WeaponAttackType attType) const;
	float GetWeaponDamageRange(WeaponAttackType attType,
			WeaponDamageRange type) const;
	void SetBaseWeaponDamage(WeaponAttackType attType,
			WeaponDamageRange damageRange, float value) {
		m_weaponDamage[attType][damageRange] = value;
	}

	bool isInFrontInMap(Unit const* target, float distance,
			float arc = M_PI) const;
	void SetInFront(Unit const* target) {
		if (!HasUnitState(UNIT_STAT_CANNOT_TURN))
			SetOrientation(GetAngle(target));
	}
	bool isInBackInMap(Unit const* target, float distance,
			float arc = M_PI) const;
	void SetFacingToObject(WorldObject* pObject);

	// Visibility system
	bool IsVisible() const {
		return (m_serverSideVisibility.GetValue(SERVERSIDE_VISIBILITY_GM)
				> SEC_PLAYER) ? false : true;
	}
	void SetVisible(bool x);

	// common function for visibility checks for player/creatures with detection code
	bool isValid() const {
		return WorldObject::isValid();
	}

	void SetPhaseMask(uint32 newPhaseMask, bool update); // overwrite WorldObject::SetPhaseMask
	void UpdateObjectVisibility(bool forced = true);

	SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY];
	uint32 m_lastSanctuaryTime;

	// Threat related methods
	bool CanHaveThreatList() const;
	void AddThreat(Unit* pVictim, float fThreat, SpellSchoolMask schoolMask =
			SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL);
	float ApplyTotalThreatModifier(float fThreat, SpellSchoolMask schoolMask =
			SPELL_SCHOOL_MASK_NORMAL);
	void DeleteThreatList();
	void TauntApply(Unit* pVictim);
	void TauntFadeOut(Unit *taunter);
	ThreatManager& getThreatManager() {
		return m_ThreatManager;
	}
	void addHatedBy(HostileReference* pHostileReference) {
		m_HostileRefManager.insertFirst(pHostileReference);
	}
	;
	void removeHatedBy(HostileReference* /*pHostileReference*/) { /* nothing to do yet */
	}
	HostileRefManager& getHostileRefManager() {
		return m_HostileRefManager;
	}

	VisibleAuraMap const *GetVisibleAuras() {
		return &m_visibleAuras;
	}
	AuraApplication * GetVisibleAura(uint8 slot) {
		VisibleAuraMap::iterator itr = m_visibleAuras.find(slot);
		if (itr != m_visibleAuras.end())
			return itr->second;
		return 0;
	}
	void SetVisibleAura(uint8 slot, AuraApplication * aur) {
		m_visibleAuras[slot] = aur;
		UpdateAuraForGroup(slot);
	}
	void RemoveVisibleAura(uint8 slot) {
		m_visibleAuras.erase(slot);
		UpdateAuraForGroup(slot);
	}

	uint32 GetInterruptMask() const {
		return m_interruptMask;
	}
	void AddInterruptMask(uint32 mask) {
		m_interruptMask |= mask;
	}
	void UpdateInterruptMask();

	uint32 GetDisplayId() {
		return GetUInt32Value(UNIT_FIELD_DISPLAYID);
	}
	void SetDisplayId(uint32 modelId);
	uint32 GetNativeDisplayId() {
		return GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID);
	}
	void RestoreDisplayId();
	void SetNativeDisplayId(uint32 modelId) {
		SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, modelId);
	}
	void setTransForm(uint32 spellid) {
		m_transform = spellid;
	}
	uint32 getTransForm() const {
		return m_transform;
	}

	// DynamicObject management
	void _RegisterDynObject(DynamicObject* dynObj);
	void _UnregisterDynObject(DynamicObject* dynObj);
	DynamicObject* GetDynObject(uint32 spellId);
	void RemoveDynObject(uint32 spellId);
	void RemoveAllDynObjects();

	GameObject* GetGameObject(uint32 spellId) const;
	void AddGameObject(GameObject* gameObj);
	void RemoveGameObject(GameObject* gameObj, bool del);
	void RemoveGameObject(uint32 spellid, bool del);
	void RemoveAllGameObjects();

	uint32 CalculateDamage(WeaponAttackType attType, bool normalized,
			bool addTotalPct);
	float GetAPMultiplier(WeaponAttackType attType, bool normalized);
	void ModifyAuraState(AuraState flag, bool apply);
	uint32 BuildAuraStateUpdateForTarget(Unit * target) const;
	bool HasAuraState(AuraState flag, SpellEntry const *spellProto = NULL,
			Unit const * Caster = NULL) const;
	void UnsummonAllTotems();
	Unit* SelectMagnetTarget(Unit *victim, SpellEntry const *spellInfo = NULL);
	int32 SpellBaseDamageBonus(SpellSchoolMask schoolMask);
	int32 SpellBaseHealingBonus(SpellSchoolMask schoolMask);
	int32 SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim);
	int32 SpellBaseHealingBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim);
	uint32 SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 effIndex, uint32 damage, DamageEffectType damagetype, uint32 stack = 1);
	uint32 SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 effIndex, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1);
	bool isSpellBlocked(Unit *pVictim, SpellEntry const *spellProto, WeaponAttackType attackType = BASE_ATTACK);
	bool isBlockCritical();
	bool isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK) const;
	uint32 SpellCriticalDamageBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim);
	uint32 SpellCriticalHealingBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim);

	void SetLastManaUse(uint32 spellCastTime) {
		m_lastManaUse = spellCastTime;
	}
	bool IsUnderLastManaUseEffect() const;

	void SetContestedPvP(Player *attackedPlayer = NULL);

	void MeleeDamageBonus(Unit *pVictim, uint32 *damage,
			WeaponAttackType attType, SpellEntry const *spellProto = NULL);
	uint32 GetCastingTimeForBonus(SpellEntry const *spellProto,
			DamageEffectType damagetype, uint32 CastingTime);

	uint32 GetRemainingDotDamage(uint64 caster, uint32 spellId,
			uint8 effectIndex = 0) const;

	void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply);
	void ApplySpellDispelImmunity(const SpellEntry * spellProto,
			DispelType type, bool apply);
	virtual bool IsImmunedToSpell(SpellEntry const* spellInfo);
	// redefined in Creature
	bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask);
	bool IsImmunedToDamage(SpellEntry const* spellInfo);
	virtual bool IsImmunedToSpellEffect(SpellEntry const* spellInfo,
			uint32 index) const;
	// redefined in Creature
	uint32 CalcNotIgnoreDamageRedunction(uint32 damage,
			SpellSchoolMask damageSchoolMask);
	static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask,
			SpellEntry const *spellInfo = NULL, uint8 effIndex =
					MAX_SPELL_EFFECTS);
	uint32 CalcArmorReducedDamage(Unit* pVictim, const uint32 damage,
			SpellEntry const *spellInfo, WeaponAttackType attackType =
					MAX_ATTACK);
	void CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask,
			DamageEffectType damagetype, const uint32 damage, uint32 *absorb,
			uint32 *resist, SpellEntry const *spellInfo = NULL);
	void CalcHealAbsorb(Unit *pVictim, const SpellEntry *spellProto,
			uint32 &healAmount, uint32 &absorb);

	void UpdateSpeed(UnitMoveType mtype, bool forced);
	float GetSpeed(UnitMoveType mtype) const;
	float GetSpeedRate(UnitMoveType mtype) const {
		return m_speed_rate[mtype];
	}
	void SetSpeed(UnitMoveType mtype, float rate, bool forced = false);
	float m_TempSpeed;

	void SetHover(bool on);
	bool isHover() const {
		return HasAuraType(SPELL_AURA_HOVER);
	}
	bool isCamouflaged() const {
		return HasAuraType(SPELL_AURA_MOD_CAMOUFLAGE);
	}

	int32 ApplyEffectModifiers(SpellEntry const* spellProto, uint8 effect_index,
			int32 value) const;
	int32 CalculateSpellDamage(Unit const* target, SpellEntry const* spellProto,
			uint8 effect_index, int32 const* basePoints = NULL) const;
	int32 CalcSpellDuration(SpellEntry const* spellProto);
	int32 ModSpellDuration(SpellEntry const* spellProto, Unit const* target,
			int32 duration, bool positive);
	void ModSpellCastTime(SpellEntry const* spellProto, int32 & castTime,
			Spell * spell = NULL);
	float CalculateLevelPenalty(SpellEntry const* spellProto) const;

	void addFollower(FollowerReference* pRef) {
		m_FollowingRefManager.insertFirst(pRef);
	}
	void removeFollower(FollowerReference* /*pRef*/) { /* nothing to do yet */
	}
	static Unit* GetUnit(WorldObject& object, uint64 guid);
	static Player* GetPlayer(WorldObject& object, uint64 guid);
	static Creature* GetCreature(WorldObject& object, uint64 guid);

    MotionMaster* GetMotionMaster() { return &i_motionMaster; }
    const MotionMaster* GetMotionMaster() const { return &i_motionMaster; }

	bool IsStopped() const {
		return !(HasUnitState(UNIT_STAT_MOVING));
	}
	void StopMoving();

	void AddUnitMovementFlag(uint32 f) {
		m_movementInfo.flags |= f;
	}
	void RemoveUnitMovementFlag(uint32 f) {
		m_movementInfo.flags &= ~f;
	}
	uint32 HasUnitMovementFlag(uint32 f) const {
		return m_movementInfo.flags & f;
	}
	uint32 GetUnitMovementFlags() const {
		return m_movementInfo.flags;
	}
	void SetUnitMovementFlags(uint32 f) {
		m_movementInfo.flags = f;
	}

	void AddExtraUnitMovementFlag(uint16 f) {
		m_movementInfo.flags2 |= f;
	}
	void RemoveExtraUnitMovementFlag(uint16 f) {
		m_movementInfo.flags2 &= ~f;
	}
	uint16 HasExtraUnitMovementFlag(uint16 f) const {
		return m_movementInfo.flags2 & f;
	}
	uint16 GetExtraUnitMovementFlags() const {
		return m_movementInfo.flags2;
	}
	void SetExtraUnitMovementFlags(uint16 f) {
		m_movementInfo.flags2 = f;
	}

	void SetControlled(bool apply, UnitState state);

	void AddComboPointHolder(uint32 lowguid) {
		m_ComboPointHolders.insert(lowguid);
	}
	void RemoveComboPointHolder(uint32 lowguid) {
		m_ComboPointHolders.erase(lowguid);
	}
	void ClearComboPointHolders();

	///----------Pet responses methods-----------------
	void SendPetCastFail(uint32 spellid, SpellCastResult msg);
	void SendPetActionFeedback(uint8 msg);
	void SendPetTalk(uint32 pettalk);
	void SendPetAIReaction(uint64 guid);
	///----------End of Pet responses methods----------

	void propagateSpeedChange() {
		GetMotionMaster()->propagateSpeedChange();
	}

	// reactive attacks
	void ClearAllReactives();
	void StartReactiveTimer(ReactiveType reactive) {
		m_reactiveTimer[reactive] = REACTIVE_TIMER_START;
	}
	void UpdateReactives(uint32 p_time);

	// group updates
	void UpdateAuraForGroup(uint8 slot);

	// proc trigger system
	bool CanProc() {
		return !m_procDeep;
	}
	void SetCantProc(bool apply) {
		if (apply)
			++m_procDeep;
		else {
			ASSERT(m_procDeep);
			--m_procDeep;
		}
	}

	// pet auras
	typedef std::set<PetAura const*> PetAuraSet;
	PetAuraSet m_petAuras;
	void AddPetAura(PetAura const* petSpell);
	void RemovePetAura(PetAura const* petSpell);

	uint32 GetModelForForm(ShapeshiftForm form);
	uint32 GetModelForTotem(PlayerTotemType totemType);

	void SetReducedThreatPercent(uint32 pct, uint64 guid) {
		m_reducedThreatPercent = pct;
		m_misdirectionTargetGUID = guid;
	}
	uint32 GetReducedThreatPercent() {
		return m_reducedThreatPercent;
	}
	Unit *GetMisdirectionTarget() {
		return m_misdirectionTargetGUID ?
				GetUnit(*this, m_misdirectionTargetGUID) : NULL;
	}

	bool IsAIEnabled, NeedChangeAI;
	bool CreateVehicleKit(uint32 id);
	void RemoveVehicleKit();
	Vehicle *GetVehicleKit() const {
		return m_vehicleKit;
	}
	Vehicle *GetVehicle() const {
		return m_vehicle;
	}
	bool IsOnVehicle(const Unit *vehicle) const {
		return m_vehicle && m_vehicle == vehicle->GetVehicleKit();
	}
	Unit *GetVehicleBase() const;
	Creature *GetVehicleCreatureBase() const;
	float GetTransOffsetX() const {
		return m_movementInfo.t_pos.GetPositionX();
	}
	float GetTransOffsetY() const {
		return m_movementInfo.t_pos.GetPositionY();
	}
	float GetTransOffsetZ() const {
		return m_movementInfo.t_pos.GetPositionZ();
	}
	float GetTransOffsetO() const {
		return m_movementInfo.t_pos.GetOrientation();
	}
	uint32 GetTransTime() const {
		return m_movementInfo.t_time;
	}
	int8 GetTransSeat() const {
		return m_movementInfo.t_seat;
	}
	uint64 GetTransGUID() const;

	bool m_ControlledByPlayer;

	bool CheckPlayerCondition(Player* pPlayer);
	void EnterVehicle(Unit *base, int8 seatId = -1, bool byAura = false) {
		EnterVehicle(base->GetVehicleKit(), seatId, byAura);
	}
	void EnterVehicle(Vehicle *vehicle, int8 seatId = -1, bool byAura = false);
	void ExitVehicle();
	void ChangeSeat(int8 seatId, bool next = true, bool byAura = false);

	void BuildMovementPacket(ByteBuffer *data) const;

	bool isMoving() const {
		return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_MOVING);
	}
	bool isTurning() const {
		return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_TURNING);
	}
	bool canFly() const {
		return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY);
	}
	bool IsFlying() const {
		return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING);
	}
	void SetFlying(bool apply);

	void RewardRage(uint32 damage, uint32 weaponSpeedHitFactor, bool attacker);

	virtual float GetFollowAngle() const {
		return static_cast<float>(M_PI / 2);
	}

	void OutDebugInfo() const;
	virtual bool isBeingLoaded() const {
		return false;
	}
	bool IsDuringRemoveFromWorld() const {
		return m_duringRemoveFromWorld;
	}

	Pet* ToPet() {
		if (isPet())
			return reinterpret_cast<Pet*>(this);
		else
			return NULL;
	}
	Totem* ToTotem() {
		if (isTotem())
			return reinterpret_cast<Totem*>(this);
		else
			return NULL;
	}
	TempSummon* ToTempSummon() {
		if (isSummon())
			return reinterpret_cast<TempSummon*>(this);
		else
			return NULL;
	}
	const TempSummon* ToTempSummon() const {
		if (isSummon())
			return reinterpret_cast<const TempSummon*>(this);
		else
			return NULL;
	}

	int32 eclipse;
	int32 GetEclipsePower() {
		return eclipse;
	}
	;
	void SetEclipsePower(int32 power);

	uint32 m_heal_done[120];
	uint32 m_damage_done[120];
	uint32 m_damage_taken[120];
	int32 DmgandHealDoneTimer;
	uint32 GetHealingDoneInPastSecs(uint32 secs);
	uint32 GetDamageDoneInPastSecs(uint32 secs);
	uint32 GetDamageTakenInPastSecs(uint32 secs);
	void ResetDamageDoneInPastSecs(uint32 secs);
	void ResetHealingDoneInPastSecs(uint32 secs);

	float m_AbsorbHeal;
	float GetAbsorbHeal() const {
		return m_AbsorbHeal;
	}
	;
	void SetAbsorbHeal(float heal) {
		m_AbsorbHeal = heal;
	}
	;
    void SetTarget(uint64 guid)
    {
        if (!_targetLocked)
            SetUInt64Value(UNIT_FIELD_TARGET, guid);
    }
protected:
	explicit Unit();

	UnitAI *i_AI, *i_disabledAI;

	void _UpdateSpells(uint32 time);
	void _DeleteRemovedAuras();

	void _UpdateAutoRepeatSpell();

	bool m_AutoRepeatFirstCast;

	uint32 m_attackTimer[MAX_ATTACK];

	float m_createStats[MAX_STATS];

	AttackerSet m_attackers;
	Unit* m_attacking;

	DeathState m_deathState;

	int32 m_procDeep;

	typedef std::list<DynamicObject*> DynObjectList;
	DynObjectList m_dynObj;

	typedef std::list<GameObject*> GameObjectList;
	GameObjectList m_gameObj;
	bool m_isSorted;
	uint32 m_transform;

	AuraMap m_ownedAuras;
	AuraApplicationMap m_appliedAuras;
	AuraList m_removedAuras;
	AuraMap::iterator m_auraUpdateIterator;
	uint32 m_removedAurasCount;

	AuraEffectList m_modAuras[TOTAL_AURAS];
	AuraList m_scAuras; // casted singlecast auras
	AuraApplicationList m_interruptableAuras; // auras which have interrupt mask applied on unit
	AuraStateAurasMap m_auraStateAuras; // Used for improve performance of aura state checks on aura apply/remove
	uint32 m_interruptMask;

	float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END];
	float m_weaponDamage[MAX_ATTACK][2];
	bool m_canModifyStats;
	VisibleAuraMap m_visibleAuras;

	float m_speed_rate[MAX_MOVE_TYPE];

	CharmInfo *m_charmInfo;
	SharedVisionList m_sharedVision;

	virtual SpellSchoolMask GetMeleeDamageSchoolMask() const;

	MotionMaster i_motionMaster;
	//uint32 m_unit_movement_flags;

	uint32 m_reactiveTimer[MAX_REACTIVE];
	uint32 m_regenTimer;

	ThreatManager m_ThreatManager;

	Vehicle *m_vehicle;
	Vehicle *m_vehicleKit;

	uint32 m_unitTypeMask;

	bool isAlwaysVisibleFor(WorldObject const* seer) const;
	bool canSeeAlways(WorldObject const* obj) const {
		return WorldObject::canSeeAlways(obj);
	}

	bool isVisibleForInState(WorldObject const* seer) const {
		return WorldObject::isVisibleForInState(seer);
	}
	;

	bool isAlwaysDetectableFor(WorldObject const* seer) const;

private:
	bool IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura * aura,
			SpellEntry const * procSpell, uint32 procFlag, uint32 procExtra,
			WeaponAttackType attType, bool isVictim, bool active,
			SpellProcEventEntry const *& spellProcEvent);
	bool HandleDummyAuraProc(Unit *pVictim, uint32 damage,
			AuraEffect* triggeredByAura, SpellEntry const *procSpell,
			uint32 procFlag, uint32 procEx, uint32 cooldown);
	bool HandleModDamagePctTakenAuraProc(Unit *pVictim, uint32 damage,
			AuraEffect* triggeredByAura, SpellEntry const *procSpell,
			uint32 procFlag, uint32 procEx, uint32 cooldown);
	bool HandleSpellCritChanceAuraProc(Unit *pVictim, uint32 damage,
			AuraEffect* triggredByAura, SpellEntry const *procSpell,
			uint32 procFlag, uint32 procEx, uint32 cooldown);
	bool HandleObsModEnergyAuraProc(Unit *pVictim, uint32 damage,
			AuraEffect* triggeredByAura, SpellEntry const *procSpell,
			uint32 procFlag, uint32 procEx, uint32 cooldown);
	bool HandleModPowerRegenAuraProc(Unit *pVictim, uint32 damage,
			AuraEffect* triggeredByAura, SpellEntry const *procSpell,
			uint32 procFlag, uint32 procEx, uint32 cooldown);
	bool HandleAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura,
			SpellEntry const * procSpell, uint32 procFlag, uint32 procEx,
			uint32 cooldown, bool * handled);
	bool HandleProcTriggerSpell(Unit *pVictim, uint32 damage,
			AuraEffect* triggeredByAura, SpellEntry const *procSpell,
			uint32 procFlag, uint32 procEx, uint32 cooldown);
	bool HandleOverrideClassScriptAuraProc(Unit *pVictim, uint32 damage,
			AuraEffect* triggeredByAura, SpellEntry const *procSpell,
			uint32 cooldown);
	bool HandleAuraRaidProcFromChargeWithValue(AuraEffect* triggeredByAura);
	bool HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura);

	// player or player's pet
	float GetCombatRatingReduction(CombatRating cr) const;
	uint32 GetCombatRatingDamageReduction(CombatRating cr, float rate,
			float cap, uint32 damage) const;

	void SetFeared(bool apply);
	void SetConfused(bool apply);
	void SetStunned(bool apply);
	void SetRooted(bool apply);

	uint32 m_rootTimes;

	uint32 m_state; // Even derived shouldn't modify
	uint32 m_CombatTimer;
	uint32 m_lastManaUse; // msecs

	Spell* m_currentSpells[CURRENT_MAX_SPELL];

	Diminishing m_Diminishing;
	// Manage all Units threatening us
	// ThreatManager m_ThreatManager;
	// Manage all Units that are threatened by us
	HostileRefManager m_HostileRefManager;

	FollowerRefManager m_FollowingRefManager;

	ComboPointHolderSet m_ComboPointHolders;

	uint32 m_reducedThreatPercent;
	uint64 m_misdirectionTargetGUID;

	bool m_cleanupDone; // lock made to not add stuff after cleanup before delete
	bool m_duringRemoveFromWorld; // lock made to not add stuff after begining removing from world
    Spell const* _focusSpell;
    bool _targetLocked; // locks the target during spell cast for proper facing
};

namespace Trinity {
// Binary predicate for sorting Units based on percent value of a power
class PowerPctOrderPred {
public:
	PowerPctOrderPred(Powers power, bool ascending = true) :
			m_power(power), m_ascending(ascending) {
	}
	bool operator()(const Unit *a, const Unit *b) const {
		float rA =
				a->GetMaxPower(m_power) ?
						float(a->GetPower(m_power))
								/ float(a->GetMaxPower(m_power)) :
						0.0f;
		float rB =
				b->GetMaxPower(m_power) ?
						float(b->GetPower(m_power))
								/ float(b->GetMaxPower(m_power)) :
						0.0f;
		return m_ascending ? rA < rB : rA > rB;
	}
private:
	const Powers m_power;
	const bool m_ascending;
};

// Binary predicate for sorting Units based on percent value of health
class HealthPctOrderPred {
public:
	HealthPctOrderPred(bool ascending = true) :
			m_ascending(ascending) {
	}
	bool operator()(const Unit *a, const Unit *b) const {
		float rA =
				a->GetMaxHealth() ?
						float(a->GetHealth()) / float(a->GetMaxHealth()) : 0.0f;
		float rB =
				b->GetMaxHealth() ?
						float(b->GetHealth()) / float(b->GetMaxHealth()) : 0.0f;
		return m_ascending ? rA < rB : rA > rB;
	}
private:
	const bool m_ascending;
};
}

template<typename Elem, typename Node>
inline void Unit::SendMonsterMoveByPath(Path<Elem, Node> const& path
		, uint32 start, uint32 end) {
	uint32 traveltime = uint32(path.GetTotalLength(start, end) * 32);
	uint32 pathSize = end - start;
	WorldPacket data(
			SMSG_MONSTER_MOVE,
			(GetPackGUID().size() + 1 + 4 + 4 + 4 + 4 + 1 + 4 + 4 + 4
					+ pathSize * 4 * 3));
	data.append(GetPackGUID());
	data << uint8(0);
	data << GetPositionX();
	data << GetPositionY();
	data << GetPositionZ();
	data << uint32(getMSTime());
	data << uint8(0);
	data
			<< uint32(
					((GetUnitMovementFlags() & MOVEMENTFLAG_LEVITATING)
							|| isInFlight()) ?
							(SPLINEFLAG_FLYING | SPLINEFLAG_WALKING) :
							SPLINEFLAG_WALKING);
	data << uint32(traveltime);
	data << uint32(pathSize);

	for (uint32 i = start; i < end; ++i) {
		data << float(path[i].x);
		data << float(path[i].y);
		data << float(path[i].z);
	}

	SendMessageToSet(&data, true);
}
#endif
